Skip to content

Commit

Permalink
Merge pull request #62 from frozeman/v1.0
Browse files Browse the repository at this point in the history
## v1.0

- Update codebase to ES6;
- Overall codebase refactoring and linting;
- __Breaking__: Remove spinner, `simple-spinner` dependency, and `-hide, --hideSpinner` command line options;
- Support for modern (ES6) and legacy (ES5) builds (legacy build is used by default);
- Support for Meteor's `<meteor-bundled-js/>` and `<meteor-bundled-css/>`;
- Support for `body.html` and `blaze-html-templates` (see updated readme);
- Support for `{{url-to-meteor-bundled-css}}` placeholder, which can be used in `<link rel="preload">`;
- __Breaking__: `--usebuild` option now accepts `<path>` to the build;
- Update NPM dependencies;
- Use `fs-extra` module to move files around;
- Check that `Meteor` and `Meteor.disconnect` exist in global space;
- If `--url` option is not passed create dummy `sockjs/info` to avoid connect DDP exceptions;
- Closing: #53, #40;
- Solving: #61, #57, #55, #42, #18;
- Taking into account: #59, #35;
  • Loading branch information
dr-dimitru authored Aug 11, 2020
2 parents 70378a3 + b99d461 commit 8e6f97e
Show file tree
Hide file tree
Showing 10 changed files with 590 additions and 430 deletions.
2 changes: 1 addition & 1 deletion .versions
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ ecmascript-runtime@0.7.0
ecmascript-runtime-client@0.10.0
ecmascript-runtime-server@0.9.0
fetch@0.1.1
frozeman:build-client@0.4.3
frozeman:build-client@1.0.0
inter-process-messaging@0.1.1
meteor@1.9.3
minifier-css@1.5.0
Expand Down
158 changes: 93 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,29 @@

# Meteor Build Client

This tool builds and bundles the client part of a Meteor app with a simple index.html,
so it can be hosted on any server or even loaded via the `file://` protocol.
This tool builds and bundles the client part of a Meteor app with a simple `index.html`, so it can be hosted on any server or even loaded via the `file://` protocol.

## Installation

$ [sudo] npm install -g meteor-build-client
```shell
npm install -g meteor-build-client
```

## Usage

// cd into your meteor app
$ cd myApp
```shell
// cd into your meteor app
cd /my/app

// run meteor-build-client
meteor-build-client ../output/directory
```

// run meteor-build-client
$ meteor-build-client ../myOutputFolder
## Important notes:

**Warning** the content of the output folder will be deleted before building the new output! So dont do things like
`$ meteor-build-client /home`!
- __Warning__: the content of the output folder will be deleted before building the new output! So don't do things like `meteor-build-client /home`!
- __Do not use dynamic imports!__ e.g. `import('/eager/file');`;
- By default this package link __legacy__ ES5 bundle build.

### Output

Expand All @@ -33,117 +39,139 @@ The content of the output folder could look as follows:

For a list of options see:

$ meteor-build-client --help
```shell
meteor-build-client --help
```

### Passing a settings.json

You can pass an additional settings file using the `--settings` or `-s` option:

$ meteor-build-client ../myOutputFolder -s ../settings.json
```shell
meteor-build-client ../output/directory -s ../settings.json
```

**Note** Only the `public` property of that JSON file will be add to the `Meteor.settings` property.


### App URL

Additionally you can set the `ROOT_URL` of your app using the `--url` or `-u` option:

$ meteor-build-client ../myOutputFolder -u http://myserver.com

If you pass `"default"`, your app will try to connect to the server where the application was served from.
```shell
meteor-build-client ../output/directory -u https://myserver.com
```

If this option was not set, it will set the server to `""` (empty string) and will add a `Meteor.disconnect()` after Meteor was loaded.
If you pass `"default"`, your app will try to connect to the server where the application was served from. If this option was not set, it will set the server to `""` (empty string) and will add a `Meteor.disconnect()` after Meteor was loaded.

### Absolute or relative paths

If you want to be able to start you app by simply opening the index.html (using the `file://` protocol),
you need to link your files relative. You can do this by setting the `--path` or `-p` option:
If you want to be able to start you app by simply opening the index.html (using the `file://` protocol), you need to link your files relative. You can do this by setting the `--path` or `-p` option:

$ meteor-build-client ../myOutputFolder -p ""
```shell
meteor-build-client ../output/directory -p ""
```

The default path value is `"/"`.

*Note* When set a path value, it will also replace this path in you Meteor CSS file, so that fonts etc link correctly.


### Using your own build folder

If you want to use your own build folder by running `meteor build` yourself, specify the `--usebuild` flag and meteor-build-client will not run the meteor build command for you. It will expect that the build folder be located up a directory from the app folder (A sibling to /app, Meteor's default location).
To use pre-build Meteor application, built using `meteor build` command manually, specify the `--usebuild <path-to-build>` flag and `meteor-build-client` will not run the `meteor build` command.

### Using custom templates
### Recommended packages for client-only build

If you want to provide a custom template for the initial HTML provide an HTML file with the `--template` or `-t` option:
If you're building server-less standalone web application we recommend to replace `meteor-base` with `meteor` and `webapp` packages.

$ meteor-build-client ../myOutputFolder -t ../myTemplate.html
```diff
@@ .meteor/packages
- meteor-base
+ meteor
+ webapp
```

The template file need to contain the following placholders: `{{> head}}`, `{{> css}}` and `{{> scripts}}`.
The following example adds a simple loading text to the initial HTML file (Your app should later take care of removing the loading text):
### Template

Following Meteor's recommended usage of `<meteor-bundled-css />` and `<meteor-bundled-js/>` this tags will be replaced with links to generated CSS and JS files respectively. Optionally, use `{{url-to-meteor-bundled-css}}` as a placeholder for URL to generated CSS file. We encourage to use `static-html` (*for non-Blaze projects*) or `blaze-html-templates` (*for Blaze projects*) package for creating bare HTML template in your app, minimal example:

```html
<!-- client/head.html -->
<head>
<meta charset="UTF-8">
<!-- recommended "fragment" to mark as JS-powered website for search engines -->
<meta name="fragment" content="!">

<title>My Meteor App</title>

<!-- recommended "preload" for CSS bundle file -->
<link rel="preload" href="{{url-to-meteor-bundled-css}}" as="style">
<meteor-bundled-css />
</head>
```

Where `<meteor-bundled-css />` will be replaced with `<link />` element to generated CSS file(s) and `{{url-to-meteor-bundled-css}}` will be replaced with URL to generated CSS file.

```html
<!DOCTYPE html>
<html>
<head>
{{> head}}
<link rel="stylesheet" type="text/css" href="/loadingScreen.css">
</head>
<body>
<h1>Loading...</h1>

{{> css}}
{{> scripts}}
</body>
</html>
<!-- client/body.html -->
<body>
<meteor-bundled-js />
</body>
```
By linking a file from your `public` folder (e.g. `loadingScreen.css`) and moving the `{{> css}}` and `{{> scripts}}` placeholder to the end of the `<body>` tag,
you can simply style your loading screen.
Because the small CSS file (`loadingScreen.css`) and the body content will be loaded *before* the Meteor app script, the the user sees the nice Loading text.

Where `<meteor-bundled-js />` will be replaced with `<script />` element(s) to generated JS file(s).

## Connecting to a Meteor server

In order to connect to a Meteor servers, create DDP connection by using `DDP.connect()`, as seen in the following example:

```js
// This Should be in both server and client in a lib folder
DDPConnection = (Meteor.isClient) ? DDP.connect("http://localhost:3000/") : {};
DDPConnection = (Meteor.isClient) ? DDP.connect('http://localhost:3000/') : {};

// When creating a new collection on the client use:
if(Meteor.isClient) {
posts = new Mongo.Collection("posts", DDPConnection);
posts = new Mongo.Collection('posts', DDPConnection);

// set the new DDP connection to all internal packages, which require one
Meteor.connection = DDPConnection;
Accounts.connection = Meteor.connection;
Meteor.users = new Mongo.Collection('users');
Meteor.connection.subscribe('users');
// set the new DDP connection to all internal packages, which require one
Meteor.connection = DDPConnection;
Accounts.connection = Meteor.connection;
Meteor.users = new Mongo.Collection('users');
Meteor.connection.subscribe('users');

// And then you subscribe like this:
DDPConnection.subscribe("mySubscription");
// And then you subscribe like this:
DDPConnection.subscribe('mySubscription');
}
```

## Making routing work on a non Meteor server

To be able to open URLs and let them be handled by the client side JavaScript, you need to rewrite URLs on the server side, so they point always to your index.html.
To be able to open URLs and let them be handled by the client side JavaScript, you need to rewrite URLs on the server side, so they point always to `index.html`

### Apache

For apache a `.htaccess` with `mod_rewrite` could look as follow:

```bash
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

# Always pass through requests for files that exist
# Per http://stackoverflow.com/a/7090026/223225
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]

# Send all other requests to index.html where the JavaScript router can take over
# and render the requested route
RewriteRule ^.*$ index.html [L]
RewriteEngine On
RewriteBase /

# Always pass through requests for files that exist
# Per http://stackoverflow.com/a/7090026/223225
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule . - [L]

# Send all other requests to index.html where the JavaScript router can take over
# and render the requested route
RewriteRule ^.*$ index.html [L]
</IfModule>
```

For nginx:
### nginx:

Use `try_files` and `error_page` to redirect all requests to non-existent files to `index.html`

```conf
server {
listen 80;
Expand Down
5 changes: 5 additions & 0 deletions helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
print(...args) {
console.info.apply(console, args);
}
};
10 changes: 1 addition & 9 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,2 @@
<!DOCTYPE html>
<html>
<head>
{{> css}}
{{> scripts}}
{{> head}}
</head>
<body>
</body>
</html>
<html><head>{{> head}}</head><body>{{> body}}</body></html>
Loading

0 comments on commit 8e6f97e

Please sign in to comment.