1 | # Advanced topics
|
2 |
|
3 | This section helps you to dig deeper into the project.
|
4 |
|
5 | ## Important files and directories
|
6 |
|
7 | | Filename | Description |
|
8 | |----------------|-------------|
|
9 | | `dist/` | Build output |
|
10 | | `dist/website/` | Compiled web server ready to run by itself or hosted on IIS |
|
11 | | `dist/website/public/` | Bundled content and static assets |
|
12 | | `dist/packages/web.zip` | Web server packed by MSDeploy and ready to deploy to Azure Web Apps |
|
13 | | [`src/app.js`](src/app.js) | Depends on `NODE_ENV`, development mode serves content directly from [`web/`](web/), production mode serves content from `dist/website/public` |
|
14 | | [`src/controllers/api.js`](src/controllers/api.js) | RESTful API hosted at [http://localhost/api](http://localhost/api) |
|
15 | | [`src/iisnode.yml`](src/iisnode.yml) | [iisnode configuration](https://tomasz.janczuk.org/2012/05/yaml-configuration-support-in-iisnode.html) |
|
16 | | [`src/web.config`](src/web.config) | `Web.config` for hosting under Azure Web App and IIS |
|
17 | | [`scripts/`](scripts) | Gulpfile for building and packing the project |
|
18 | | [`web/files/`](web/files) | Asset source files |
|
19 | | [`web/src/`](web/src) | JavaScript source files |
|
20 |
|
21 | ## NPM scripts
|
22 |
|
23 | To help building the project, there are several NPM scripts.
|
24 |
|
25 | | Task name | Description |
|
26 | | ------------- | ----------- |
|
27 | | `build` | Start the build process |
|
28 | | `deploy` | Deploy the website to Azure Web App |
|
29 | | `host:dev` | Host a Webpack development server and bundle on-the-fly |
|
30 | | `host:prod` | Host a production server using pre-bundled files at `dist/website/` |
|
31 | | `pack` | Use MSDeploy to pack everything at `dist/website/` into `dist/packages/web.zip` |
|
32 |
|
33 | ## Building the website
|
34 |
|
35 | To build the website, run `npm run build`. The build output will be located at `dist/website/`.
|
36 |
|
37 | * Specify build favor by either
|
38 | * Set environment variable `NODE_ENV` to `production`, or
|
39 | * Run `npm run build -- --build production`
|
40 | * Specify bundler by either
|
41 | * Set environment variable `BUNDLER` to `rollup` or `webpack`, or
|
42 | * Run `npm run build -- --bundler rollup`
|
43 |
|
44 | > Currently, the build favor (either `development` or `production`) is only used by [`transform-node-env-inline`](https://babeljs.io/docs/plugins/transform-node-env-inline/). It helps reducing bundle size by excluding developer-friendly error messages in production build.
|
45 |
|
46 | ### What the build do
|
47 |
|
48 | Source code can be found at [`scripts/build.js`](scripts/build.js).
|
49 |
|
50 | * Copy server code from [`src/`](src) to `dist/website/`, exclude `node_modules` folder
|
51 | * After copy complete, will run `npm install --ignore-scripts --only=production` to install fresh packages
|
52 | * Bundle source files from [`web/src/`](web/src) to `dist/website/public/dist/bundle.js`
|
53 | * Will use existing npm packages from `web/node_modules`
|
54 | * Copy static assets from [`web/files/`](web/files) to `dist/website/public/`
|
55 | * Will minify image with [`gulp-imagemin`](https://www.npmjs.com/package/gulp-imagemin/)
|
56 | * Will minify HTML with [`gulp-htmlmin`](https://www.npmjs.com/package/gulp-htmlmin/)
|
57 |
|
58 | ## Webpack configuration
|
59 |
|
60 | The configuration file is located at [`web/webpack.config.js`](web/webpack.config.js). It controls how files are getting bundled into a monolithic `dist/website/public/js/bundle.js`.
|
61 |
|
62 | * [`web/src/*.js`](web/src) and [`web/src/*.jsx`](web/src)
|
63 | * Bundled by [`babel-loader`](https://www.npmjs.com/package/babel-loader)
|
64 | * Enable React JSX by [`preset-react`](https://babeljs.io/docs/plugins/preset-react/)
|
65 | * Enable ES2015 by [`preset-es2015`](http://babeljs.io/docs/plugins/preset-es2015/)
|
66 | * Escape ES3 reserved keywords
|
67 | * [`transform-es3-member-expression-literals`](https://babeljs.io/docs/plugins/transform-es3-member-expression-literals/)
|
68 | * [`transform-es3-property-literals`](https://babeljs.io/docs/plugins/transform-es3-property-literals/)
|
69 | * Transform `process.env.NODE_ENV` into `"development"` or `"production"` with [`transform-node-env-inline`](https://babeljs.io/docs/plugins/transform-node-env-inline/)
|
70 | * Entrypoint is [`web/src/index.js`](web/src/index.js)
|
71 | * [`web/src/*.css`](web/src) and [`web/src/*.less`](web/src)
|
72 | * Bundled by [`less-loader`](https://www.npmjs.com/package/less-loader), then
|
73 | * [`css-loader`](https://www.npmjs.com/package/css-loader), then
|
74 | * [`style-loader`](https://www.npmjs.com/package/style-loader)
|
75 |
|
76 | > We use rollup.js for bundling in production build. Since rollup.js currently only support single entrypoint and not code-splitting. If you want to enable these features, please build with `--bundler webpack` to use Webpack as bundler in production build.
|
77 |
|
78 | ## Webpack development mode configuration
|
79 |
|
80 | When running Webpack development server, additional configurations are required, for example, hot module replacement.
|
81 |
|
82 | When running under development server, we will add the following to [`webpack.config.js`](web/webpack.config.js):
|
83 |
|
84 | * Serve assets from [`web/files/`](web/files/)
|
85 | * Enable [source map](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-tools)
|
86 | * Use absolute path for source map for compatibility with Edge
|
87 | * Also write a copy of `bundle.js` to `dist/webpack/bundle.js` for debugging purpose
|
88 | * Hot module replacement
|
89 | * Support React component with [`react-hot`](https://github.com/gaearon/react-hot-loader) loader
|
90 |
|
91 | ## Rollup.js configuration
|
92 |
|
93 | The configuration file is located at [`web/rollup.config.js`](web/rollup.config.js). It is similar to Webpack configuration.
|
94 |
|
95 | * TBD: ~~[`web/src/*.less`](web/src)~~
|
96 | * ~~Bundled by [`rollup-plugin-less`](https://npmjs.com/package/rollup-plugin-less)~~
|
97 | * ~~Inject CSS styles into `<head>`~~
|
98 | * [`web/src/*.js`](web/src)
|
99 | * Bundled by [`rollup-plugin-babel`](https://www.npmjs.com/package/rollup-plugin-babel)
|
100 | * Enable ES2015 with [`preset-es2015`](http://babeljs.io/docs/plugins/preset-es2015/)
|
101 | * Enable React JSX with [`preset-react`](https://babeljs.io/docs/plugins/preset-react/)
|
102 | * Escape ES3 reserved keywords
|
103 | * [`transform-es3-member-expression-literals`](https://babeljs.io/docs/plugins/transform-es3-member-expression-literals/)
|
104 | * [`transform-es3-property-literals`](https://babeljs.io/docs/plugins/transform-es3-property-literals/)
|
105 | * Entrypoint is [`web/src/index.js`](web/src/index.js)
|
106 | * Bundled by [`rollup-plugin-commonjs`](https://www.npmjs.com/package/rollup-plugin-commonjs)
|
107 | * Convert CommonJS `require` statement into ES2015 `import` statement, including [`fbjs`](https://npmjs.com/package/fbjs), [`object-assign`](https://npmjs.com/package/object-assign), [`react`](https://npmjs.com/package/react), and [`react-dom`](https://npmjs.com/package/react-dom)
|
108 | * Bundled by [`rollup-plugin-replace`](https://www.npmjs.com/package/rollup-plugin-replace)
|
109 | * String-replace `process.env.NODE_ENV` into `"development"` or `"production"`
|
110 | * Bundled by [`rollup-plugin-node-resolve`](https://www.npmjs.com/package/rollup-plugin-node-resolve)
|
111 | * Bundle dependencies into `bundle.js`
|
112 |
|
113 | ## Enable source map output in production mode
|
114 |
|
115 | Run `npm run build -- --sourcemap true` to output `dist/website/public/js/bundle.js.map` for debugging purpose.
|
116 |
|
117 | ## Packing with MSDeploy
|
118 |
|
119 | To pack the content and production server, `npm run pack`.
|
120 |
|
121 | It will create a MSDeploy ZIP file that can be deployed to any IIS server, including [Azure Web App](https://azure.microsoft.com/en-us/services/app-service/web/). This ZIP file contains Express server code and website contents in production favor.
|
122 |
|
123 | Additional parameters added to MSDeploy ZIP file:
|
124 |
|
125 | | name | defaultValue | tags | kind | scope |
|
126 | |--------------------------|--------------------|----------|----------------|----------|
|
127 | | IIS Web Application Name | `Default Web Site` | `IisApp` | `ProviderPath` | `IisApp` |
|
128 |
|
129 | Before packing the project, make sure your current build is up-to-date, or run `npm run build`.
|
130 |
|
131 | > [MSDeploy](https://www.iis.net/downloads/microsoft/web-deploy) is only supported on Windows.
|
132 |
|
133 | ## iisnode configuration
|
134 |
|
135 | We have overrode some defaults in [`iisnode.yml`](iisnode.yml).
|
136 |
|
137 | * `debuggingEnabled` is set to `false`
|
138 | * `devErrorsEnabled` is set to `false`
|
139 | * `loggingEnabled` is set to `false`
|
140 | * `nodeProcessCountPerApplication` is set to `0`
|
141 | * One worker process per CPU
|
142 | * `node_env` is set to `production`
|
143 | * We assume hosting the site in IIS is always in production mode
|
144 | * Express is faster when environment variable `NODE_ENV` is set to `production`, details [here](http://apmblog.dynatrace.com/2015/07/22/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/)
|