From 7c00aad19cd7f36e30c8034d240cea7ea7db6c83 Mon Sep 17 00:00:00 2001 From: Leo Horie Date: Sun, 8 Jan 2017 10:53:54 -0500 Subject: [PATCH] beef up docs and defrag setup flow --- docs/es6.md | 126 ++++++++++++++++++++++++++++++++----------- docs/hyperscript.md | 9 ++++ docs/installation.md | 63 ++++++++++++++++------ docs/jsx.md | 122 ++++++++++++++++++++++++++++++++--------- 4 files changed, 246 insertions(+), 74 deletions(-) diff --git a/docs/es6.md b/docs/es6.md index e8a22000..3ab05040 100644 --- a/docs/es6.md +++ b/docs/es6.md @@ -1,69 +1,133 @@ # ES6 +- [Setup](#setup) +- [Using Babel with Webpack](#using-babel-with-webpack) + +--- + Mithril is written in ES5, and is fully compatible with ES6 as well. In some limited environments, it's possible to use a significant subset of ES6 directly without extra tooling (for example, in internal applications that do not support IE). However, for the vast majority of use cases, a compiler toolchain like [Babel](https://babeljs.io) is required to compile ES6 features down to ES5. ### Setup -The simplest way to setup an ES6 compilation toolchain is via [Babel](https://babeljs.io/). To install, use this command: +The simplest way to setup an ES6 compilation toolchain is via [Babel](https://babeljs.io/). + +Babel requires NPM, which is automatically installed when you install [Node.js](https://nodejs.org/en/). Once NPM is installed, create a project folder and run this command: ```bash -npm install babel-cli babel-preset-es2015 transform-react-jsx --save-dev +npm init -y +``` + +If you want to use Webpack and Babel together, [skip to the section below](#using-babel-with-webpack). + +To install Babel as a standalone tool, use this command: + +```bash +npm install babel-cli babel-preset-es2015 babel-plugin-transform-react-jsx --save-dev ``` Create a `.babelrc` file: ``` { - "presets": ["es2015"], - "plugins": [ - ["transform-react-jsx", { - "pragma": "m" - }] - ] + "presets": ["es2015"], + "plugins": [ + ["transform-react-jsx", { + "pragma": "m" + }] + ] } ``` To run Babel as a standalone tool, run this from the command line: ```bash -babel src --out-dir lib --source-maps +babel src --out-dir bin --source-maps ``` #### Using Babel with Webpack -If you're using Webpack as a bundler, you can integrate Babel to Webpack, however this requires some additional dependencies, in addition to the steps above. +If you're already using Webpack as a bundler, you can integrate Babel to Webpack by following these steps. ```bash -npm install babel-core babel-loader --save-dev +npm install babel-core babel-loader babel-preset-es2015 babel-plugin-transform-react-jsx --save-dev ``` -Create a file called `.webpack.config` +Create a `.babelrc` file: -```javascript -module.exports = { - entry: './src/index.js', - output: { - path: './bin', - filename: 'app.js', - }, - module: { - loaders: [{ - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader' - }] - } +``` +{ + "presets": ["es2015"], + "plugins": [ + ["transform-react-jsx", { + "pragma": "m" + }] + ] } ``` ---- +Next, create a file called `webpack.config.js` -### Custom setups +```javascript +module.exports = { + entry: './src/index.js', + output: { + path: './bin', + filename: 'app.js', + }, + module: { + loaders: [{ + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader' + }] + } +} +``` -If you're using Webpack, you can [follow its excellent guide to add support for ES6](https://webpack.github.io/docs/usage.html#transpiling-es2015-using-babel-loader) +This configuration assumes the source code file for the application entry point is in `src/index.js`, and this will output the bundle to `bin/app.js`. -If you want to use Babel as a standalone tool, [here's the instructions for how to set it up](https://babeljs.io/docs/setup/#installation). +To run the bundler, setup an npm script. Open `package.json` and add this entry under `"scripts"`: -[Google closure compiler](https://www.npmjs.com/package/google-closure-compiler) is another tool that supports ES6 to ES5 compilation. +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch" + } +} +``` + +You can now then run the bundler by running this from the command line: + +```bash +npm start +``` + +#### Production build + +To generate a minified file, open `package.json` and add a new npm script called `build`: + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch", + "build": "webpack -p" + } +} +``` + +You can use hooks in your production environment to run the production build script automatically. Here's an example for [Heroku](https://www.heroku.com/): + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch", + "build": "webpack -p", + "heroku-postbuild": "webpack -p" + } +} +``` diff --git a/docs/hyperscript.md b/docs/hyperscript.md index 6d27a4e6..6108f2d5 100644 --- a/docs/hyperscript.md +++ b/docs/hyperscript.md @@ -14,6 +14,7 @@ - [Keys](#keys) - [SVG and MathML](#svg-and-mathml) - [Making templates dynamic](#making-templates-dynamic) +- [Converting HTML](#converting-html) - [Avoid anti-patterns](#avoid-anti-patterns) --- @@ -345,6 +346,14 @@ You cannot use Javascript statements such as `if` or `for` within Javascript exp --- +### Converting HTML + +In Mithril, well-formed HTML is valid JSX. Little effort other than copy-pasting is required to integrate an independently produced HTML file into a project using JSX. + +When using hyperscript, it's necessary to convert HTML to hyperscript syntax before the code can be run. To facilitate this, you can [use the HTML-to-Mithril-template converter](http://arthurclemens.github.io/mithril-template-converter/index.html). + +--- + ### Avoid Anti-patterns Although Mithril is flexible, some code patterns are discouraged: diff --git a/docs/installation.md b/docs/installation.md index 4977f120..ddc85853 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,15 +25,15 @@ npm install webpack --save # 2) add this line into the scripts section in package.json # "scripts": { -# "build": "webpack src/index.js lib/app.js --watch" +# "start": "webpack src/index.js bin/app.js --watch" # } # 3) create an `src/index.js` file -# 4) create an `index.html` file containing `` +# 4) create an `index.html` file containing `` # 5) run bundler -npm run build +npm start # 6) open `index.html` in the (default) browser open index.html @@ -52,13 +52,13 @@ npm init --yes # creates a file called package.json ``` -Then, run +Then, to install Mithril, run: ```bash npm install mithril@rewrite --save ``` -to install Mithril. This will create a folder called `node_modules`, and a `mithril` folder inside of it. It will also add an entry under `dependencies` in the `package.json` file +This will create a folder called `node_modules`, and a `mithril` folder inside of it. It will also add an entry under `dependencies` in the `package.json` file You are now ready to start using Mithril. The recommended way to structure code is to modularize it via CommonJS modules: @@ -75,10 +75,10 @@ CommonJS is a de-facto standard for modularizing Javascript code, and it's used Most browser today do not natively support modularization systems (CommonJS or ES6), so modularized code must be bundled into a single Javascript file before running in a client-side application. -The easiest way to create a bundle is to setup an NPM script for [Webpack](https://webpack.js.org/). To install Webpack, run this from the command line: +A popular way for creating a bundle is to setup an NPM script for [Webpack](https://webpack.js.org/). To install Webpack, run this from the command line: ```bash -npm install webpack --save +npm install webpack --save-dev ``` Open the `package.json` that you created earlier, and add an entry to the `scripts` section: @@ -87,22 +87,24 @@ Open the `package.json` that you created earlier, and add an entry to the `scrip { "name": "my-project", "scripts": { - "build": "webpack index.js app.js --watch" + "start": "webpack src/index.js bin/app.js -d --watch" } } ``` -Remember this is a JSON file, so object key names such as `"scripts"` and `"build"` must be inside of double quotes. +Remember this is a JSON file, so object key names such as `"scripts"` and `"start"` must be inside of double quotes. -Now you can run the script via `npm run build` in your command line window. This looks up the `webpack` command in the NPM path, reads `index.js` and creates a file called `app.js` which includes both Mithril and the `hello world` code above. If you want to run the `webpack` command directly from the command line, you need to either add `node_modules/.bin` to your PATH, or install webpack globally via `npm install webpack -g`. It's, however, recommended that you always install webpack locally and use npm scripts, to ensure builds are reproducible in different computers. - -``` -npm run build -``` +The `-d` flag tells webpack to use development mode, which produces source maps for a better debugging experience. The `--watch` flag tells webpack to watch the file system and automatically recreate `app.js` if file changes are detected. -Now that you have created a bundle, you can then reference the `app.js` file from an HTML file: +Now you can run the script via `npm start` in your command line window. This looks up the `webpack` command in the NPM path, reads `index.js` and creates a file called `app.js` which includes both Mithril and the `hello world` code above. If you want to run the `webpack` command directly from the command line, you need to either add `node_modules/.bin` to your PATH, or install webpack globally via `npm install webpack -g`. It's, however, recommended that you always install webpack locally and use npm scripts, to ensure builds are reproducible in different computers. + +``` +npm start +``` + +Now that you have created a bundle, you can then reference the `bin/app.js` file from an HTML file: ```markup @@ -110,7 +112,7 @@ Now that you have created a bundle, you can then reference the `app.js` file fro Hello world - + ``` @@ -139,6 +141,33 @@ m.mount(document.body, MyComponent) Note that in this example, we're using `m.mount`, which wires up the component to Mithril's autoredraw system. In most applications, you will want to use `m.mount` (or `m.route` if your application has multiple screens) instead of `m.render` to take advantage of the autoredraw system, rather than re-rendering manually every time a change occurs. +#### Production build + +If you open bin/app.js, you'll notice that the Webpack bundle is not minified, so this file is not ideal for a live application. To generate a minified file, open `package.json` and add a new npm script: + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack src/index.js bin/app.js -d --watch", + "build": "webpack src/index.js bin/app.js -p", + } +} +``` + +You can use hooks in your production environment to run the production build script automatically. Here's an example for [Heroku](https://www.heroku.com/): + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch", + "build": "webpack -p", + "heroku-postbuild": "webpack -p" + } +} +``` + --- ### Alternate ways to use Mithril @@ -167,7 +196,7 @@ The source file `index.js` will be compiled (bundled) and a browser window opens #### Mithril bundler -Mithril comes with a bundler tool of its own. It is sufficient for projects that have no other dependencies other than Mithril, but it's currently considered experimental for projects that require other NPM dependencies. It produces smaller bundles than webpack, but you should not use it in production yet. +Mithril comes with a bundler tool of its own. It is sufficient for ES5-based projects that have no other dependencies other than Mithril, but it's currently considered experimental for projects that require other NPM dependencies. It produces smaller bundles than webpack, but you should not use it in production yet. If you want to try it and give feedback, you can open `package.json` and change the npm script for webpack to this: diff --git a/docs/jsx.md b/docs/jsx.md index ee6d606d..b0c0ff75 100644 --- a/docs/jsx.md +++ b/docs/jsx.md @@ -2,6 +2,7 @@ - [Description](#description) - [Setup](#setup) +- [Using Babel with Webpack](#using-babel-with-webpack) - [JSX vs hyperscript](#jsx-vs-hyperscript) - [Converting HTML](#converting-html) @@ -51,55 +52,124 @@ m.mount(document.body, ) ### Setup -The simplest way to use JSX is via a [Babel](https://babeljs.io/) plugin. To install, use this command: +The simplest way to use JSX is via a [Babel](https://babeljs.io/) plugin. + +Babel requires NPM, which is automatically installed when you install [Node.js](https://nodejs.org/en/). Once NPM is installed, create a project folder and run this command: ```bash -npm install babel-cli babel-preset-es2015 transform-react-jsx --save-dev +npm init -y +``` + +If you want to use Webpack and Babel together, [skip to the section below](#using-babel-with-webpack). + +To install Babel as a standalone tool, use this command: + +```bash +npm install babel-cli babel-preset-es2015 babel-plugin-transform-react-jsx --save-dev ``` Create a `.babelrc` file: ``` { - "presets": ["es2015"], - "plugins": [ - ["transform-react-jsx", { - "pragma": "m" - }] - ] + "presets": ["es2015"], + "plugins": [ + ["transform-react-jsx", { + "pragma": "m" + }] + ] } ``` To run Babel as a standalone tool, run this from the command line: ```bash -babel src --out-dir lib --source-maps +babel src --out-dir bin --source-maps ``` #### Using Babel with Webpack -If you're using Webpack as a bundler, you can integrate Babel to Webpack, however this requires some additional dependencies, in addition to the steps above. +If you're already using Webpack as a bundler, you can integrate Babel to Webpack by following these steps. ```bash -npm install babel-core babel-loader --save-dev +npm install babel-core babel-loader babel-preset-es2015 babel-plugin-transform-react-jsx --save-dev ``` -Create a file called `.webpack.config` +Create a `.babelrc` file: + +``` +{ + "presets": ["es2015"], + "plugins": [ + ["transform-react-jsx", { + "pragma": "m" + }] + ] +} +``` + +Next, create a file called `webpack.config.js` ```javascript module.exports = { - entry: './src/index.js', - output: { - path: './bin', - filename: 'app.js', - }, - module: { - loaders: [{ - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader' - }] - } + entry: './src/index.js', + output: { + path: './bin', + filename: 'app.js', + }, + module: { + loaders: [{ + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader' + }] + } +} +``` + +This configuration assumes the source code file for the application entry point is in `src/index.js`, and this will output the bundle to `bin/app.js`. + +To run the bundler, setup an npm script. Open `package.json` and add this entry under `"scripts"`: + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch" + } +} +``` + +You can now then run the bundler by running this from the command line: + +```bash +npm start +``` + +#### Production build + +To generate a minified file, open `package.json` and add a new npm script called `build`: + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch", + "build": "webpack -p", + } +} +``` + +You can use hooks in your production environment to run the production build script automatically. Here's an example for [Heroku](https://www.heroku.com/): + +``` +{ + "name": "my-project", + "scripts": { + "start": "webpack -d --watch", + "build": "webpack -p", + "heroku-postbuild": "webpack -p" + } } ``` @@ -107,9 +177,9 @@ module.exports = { ### JSX vs hyperscript -JSX is essentially a trade-off: it introduces a non-standard syntax that cannot be run without appropriate tooling, in order to allow a developer to write HTML code using curly braces. The main benefit of using JSX instead of regular HTML is that the JSX specification is much stricter and yields syntax errors when appropriate, whereas HTML is far too forgiving and makes syntax issues difficult to spot. +JSX is essentially a trade-off: it introduces a non-standard syntax that cannot be run without appropriate tooling, in order to allow a developer to write HTML code using curly braces. The main benefit of using JSX instead of regular HTML is that the JSX specification is much stricter and yields syntax errors when appropriate, whereas HTML is far too forgiving and can make syntax issues difficult to spot. -Unlike HTML, JSX is case-sensitive. This means `
` is different from `
` (all lower case). The former compiles to `m("div", {className: "test"})` and the latter compiles to `m("div", {classname: "test"})`, which is not a valid way of creating a class attribute). Fortunately, Mithril supports standard HTML attribute names, and thus, this example can be written like regular HTML: `
`. +Unlike HTML, JSX is case-sensitive. This means `
` is different from `
` (all lower case). The former compiles to `m("div", {className: "test"})` and the latter compiles to `m("div", {classname: "test"})`, which is not a valid way of creating a class attribute. Fortunately, Mithril supports standard HTML attribute names, and thus, this example can be written like regular HTML: `
`. JSX is useful for teams where HTML is primarily written by someone without Javascript experience, but it requires a significant amount of tooling to maintain (whereas plain HTML can, for the most part, simply be opened in a browser)