Skip to content

Commit

Permalink
feat(docs): add documentation and demo for production builds
Browse files Browse the repository at this point in the history
Fixes #8
  • Loading branch information
hotforfeature committed Apr 13, 2017
1 parent bd2186b commit e904a4e
Show file tree
Hide file tree
Showing 10 changed files with 4,046 additions and 105 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
/bundles
/lib
/dist
/build

# dependencies
/node_modules
Expand Down
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
demo/
dist/
build/
docs/
src/
.editorconfig
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ Origami bridges gaps between the Angular framework and Polymer-built custom elem
- [OnPush Change Detection ✅](docs/change-detection.md)
- [Object/Array mutation detection ✅](docs/object-array-mutation.md)
- [CSS custom property/mixin support](docs/custom-style.md)
- Ahead-of-Time Compilation ✅
- Bundled builds ❌
- ES5 compilation (IE11 and Safari 9 support) ❌
- Ahead-of-Time Compliant ✅
- [Bundled production-ready builds ✅](docs/production-build)

## Support

Expand Down
2 changes: 1 addition & 1 deletion demo/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"sourceMap": true,
"target": "es5",
"typeRoots": [
"../node_modules/@types"
"../node_modules/@types/node"
]
}
}
2 changes: 2 additions & 0 deletions docs/importing-elements.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ index.html
});
</script>
</body>
</html>
```

`<link>`s in Angular templates will not work since Angular pre-processes those templates.
Expand Down Expand Up @@ -63,6 +64,7 @@ index.html
});
</script>
</body>
</html>
```

While there is no vulcanize-like tool that works with Angular (yet!), this is likely where such a build task would start. From here, it would be easy to concatenate all imports into a single `elements-vulcanized.html` file for `index.html` to import.
134 changes: 134 additions & 0 deletions docs/production-build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# Production Build

There are two primary steps when building an Angular and Polymer application for production.

1. Compile Angular
2. Build Polymer

Origami includes a [demo app](../demo) that is built for all supported browsers and can be used as reference.

## Compile Angular

There are several ways to compile an Anglar app for production. Whatever the build process is, it's important that the `bower_components/` directory and any loose HTML files are copied from the source to the build directory.

For this guide, we will assume the application is an Angular CLI application, with `bower_components/` residing in the `assets/` folder.

```sh
ng build --prod
```

This will compile Angular for production to the `dist/` folder by default.

At this point, the app will serve correctly without any further action on ES6 browsers. However, `bower_components/` contains many unused files that will take up server space, and our app is not optimized for HTTP1 by making several import requests.

## Build Polymer

Building Polymer accomplishes a few primary goals:

- Remove unused `bower_components/` files
- Bundle HTML imports for HTTP1 effeciency
- Compile Polymer to ES5 for IE11 and Safari 9 support

We will accomplish these goals using the `polymer` CLI. Configuration options can be specified in [`polymer.json`](https://www.polymer-project.org/2.0/docs/tools/polymer-json).

### polymer.json

#### entrypoint

`polymer` takes an entrypoint HTML file where all imports reside. There are several issues when using an Angular app's `index.html` as the entrypoint, such as `polymer` loading Angular and polyfills twice.

As mentioned in [importing elements](importing-elements.md), a good strategy is to create a single separate `elements.html` file where we include our imports.

assets/elements.html
```html
<link href="bower_components/polymer/polymer.html" rel="import">
<link href="bower_components/paper-button/paper-button.html" rel="import">
<!-- You could even organize imports further into separate bundle html files -->
<link href="iron-elements.html" rel="import">
...
```

index.html
```html
<html>
<head>
<meta charset="utf-8">
<title>Paper Crane</title>
<base href="/">

<script src="assets/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link href="assets/elements.html" rel="import">
</head>
<body>
<app-root>Loading...</app-root>
<script>
window.webComponentsReady = false;
window.addEventListener('WebComponentsReady', function() {
window.webComponentsReady = true;
});
</script>
</body>
</html>
```

#### sources

`polymer` includes `src/**/*` files by default for its sources. This is not the desired behavior, since our `src/` directory contains Angular's TypeScript files, not the compiled app.

We need to include all `.js`, `.css`, and `.html` files in the Angular compiled directory as our sources. Remember that `elements.html` is our entrypoint, so we must tell `polymer` to include `index.html` as a source.

#### extraDependencies

If the app links to any scripts or HTML files in `index.html` that are not present in `elements.html`, they must be declared as extra dependencies. This will usually just be the `bower_components/webcomponentsjs/*.js` files.

#### builds

The last step to configuring `polymer` is specifying what build types to generate.

- For fewer imports, include a bundled build
- Optionally, include an unbundled build if the server supports HTTP2
- For IE11 and Safari 9, include a JS compiled build

The app server will need to dynamically serve the correct build to a browser depending on its capabilities.

#### Sample polymer.json

This JSON file assumes the Angular app was built to the `dist/` directory. It will generate three builds in the `build/` directory.

```json
{
"entrypoint": "dist/assets/elements.html",
"sources": [
"dist/*.js",
"dist/*.html",
"dist/*.css"
],
"extraDependencies": [
"dist/assets/bower_components/webcomponentsjs/*.js"
],
"builds": [
{
"name": "bundled",
"bundle": true
},
{
"name": "unbundled"
},
{
"name": "es5",
"bundle": true,
"js": { "compile": true }
}
]
}
```

This is the bare minimum configuration needed. Additional options, such as minifying HTML and CSS, can be included in each build.

Remember, only use `"js": { "compile": true }` for IE11 and Safari 9 (browsers that do not support ES6 classes). Custom Elements v1 requires that elements are ES6 classes that extend `HTMLElement`. An error will be thrown if a Custom Element v1-compliant browser attempts to load a JS compiled build.

### Cleanup

You may notice that the app's repository now has both a `dist/` and `build/` folder, and each build folder includes a `dist/` directory. With [`rimraf`](https://github.com/isaacs/rimraf) and [`cpr`](https://github.com/davglass/cpr), it is easy to include a post build script to clean up.

Look at the Origami's [`package.json`](../package.json) `build:demo` and `postbuild:demo` run scripts for reference.
9 changes: 8 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@
},
"scripts": {
"demo": "ng serve",
"clean": "rimraf lib/ bundles/",
"build:demo": "ng build --prod && polymer build && rimraf dist/",
"postbuild:demo": "npm run clean:bundled && npm run clean:unbundled && npm run clean:es5",
"clean:bundled": "cpr build/bundled/dist/ build/bundled/ && rimraf build/bundled/dist/",
"clean:unbundled": "cpr build/unbundled/dist/ build/unbundled/ && rimraf build/unbundled/dist/",
"clean:es5": "cpr build/es5/dist/ build/es5/ && rimraf build/es5/dist/",
"clean": "rimraf lib/ dist/ build/",
"lint": "tslint --project tsconfig.json",
"test": "echo \"Error: no test specified\"",
"precommit": "npm run lint",
Expand Down Expand Up @@ -49,8 +54,10 @@
"@types/node": "^7.0.12",
"codelyzer": "^3.0.0-beta.4",
"commitizen": "^2.9.6",
"cpr": "^2.0.2",
"cz-conventional-changelog": "^2.0.0",
"husky": "^0.13.3",
"polymer-cli": "next",
"rimraf": "^2.6.1",
"rxjs": "^5.0.1",
"standard-version": "^4.0.0",
Expand Down
25 changes: 25 additions & 0 deletions polymer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"entrypoint": "dist/assets/elements.html",
"sources": [
"dist/*.js",
"dist/*.html",
"dist/*.css"
],
"extraDependencies": [
"dist/assets/bower_components/webcomponentsjs/*.js"
],
"builds": [
{
"name": "bundled",
"bundle": true
},
{
"name": "unbundled"
},
{
"name": "es5",
"bundle": true,
"js": { "compile": true }
}
]
}
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
"moduleResolution": "node",
"outDir": "lib",
"sourceMap": true,
"target": "es5"
"target": "es5",
"typeRoots": [
"node_modules/@types/node"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true
Expand Down
Loading

0 comments on commit e904a4e

Please sign in to comment.