202 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			202 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# Haxe Loader for Webpack
 | 
						|
 | 
						|
This loader allows you to load hxml files directly into webpack, and included the Haxe-compiled Javascript result directly in your bundle.
 | 
						|
 | 
						|
There are several reasons for doing this:
 | 
						|
 | 
						|
- If you are going to use NPM libraries as externs, you need to compile with Webpack or Browserify etc. Having the two compile steps (Haxe and Webpack) makes it easier.
 | 
						|
- There's a good chance you'll want webpack anyway for compiling CSS (or SASS or LESS), managing static assets, or minifying the resulting JS bundle.
 | 
						|
- When Webpack is set up right, it has a nice development experience, with things like:
 | 
						|
    - `webpack --watch` to watch any changes you make to a file and recompile.
 | 
						|
    - `webpack-dev-server` to hot-reload a page based on changes you make.
 | 
						|
 | 
						|
With this loader, you are able to:
 | 
						|
 | 
						|
- Use a `hxml` file as the entry point for your build.
 | 
						|
- Change any `*.hx` source file, and have haxe re-compile, webpack re-bundle, and the browser refresh automatically as soon as you save.
 | 
						|
 | 
						|
Currently the loader only supports HXML files which export exactly one output, so you cannot use `--next` to build multiple things.  Instead you can use multiple hxml files and list each of them in Webpack.
 | 
						|
 | 
						|
If you try to build a hxml file that is for another target, like Neko, PHP or CPP - the hxml file will be executed and an empty JS file will be passed on to webpack, which you can safely ignore - see below for details.
 | 
						|
 | 
						|
### Example webpack configuration
 | 
						|
 | 
						|
```js
 | 
						|
module.exports = {
 | 
						|
    entry: {
 | 
						|
        client: './client.hxml',
 | 
						|
        server: './server.hxml', // Could compile PHP or Neko etc, does not have to be JS.
 | 
						|
    },
 | 
						|
    output: {
 | 
						|
        path: __dirname + "/www/assets",
 | 
						|
        filename: '[name].bundle.js'
 | 
						|
    },
 | 
						|
    module: {
 | 
						|
        rules: [
 | 
						|
            // Have a rule that explains hxml files should use `haxe-loader`.
 | 
						|
            {
 | 
						|
                test: /\.hxml$/,
 | 
						|
                loader: 'haxe-loader',
 | 
						|
            }
 | 
						|
        ]
 | 
						|
    },
 | 
						|
};
 | 
						|
```
 | 
						|
 | 
						|
You can also add some convenience scripts to your `package.json`:
 | 
						|
 | 
						|
```json
 | 
						|
    "scripts": {
 | 
						|
        "build": "webpack -p",
 | 
						|
        "start": "webpack-dev-server --open",
 | 
						|
        "server": "cd www && nodemon server.js",
 | 
						|
        "test": "cd www && node test.js",
 | 
						|
        "test_watch": "cd www && nodemon test.js"
 | 
						|
    },
 | 
						|
```
 | 
						|
 | 
						|
Now you can run:
 | 
						|
 | 
						|
    - `yarn build` - Use webpack to build a production copy of your app
 | 
						|
    - `yarn start` - Start the webpack dev server, which will watch for changes, recompile and refresh the browser.
 | 
						|
    - `yarn server` - Start a NodeJS server (if "www/server.js" is a NodeJS file you have compiled)
 | 
						|
    - `yarn test` - Run a test suite once (if "www/test.js" is a NodeJS file you have compiled)
 | 
						|
    - `yarn test_watch` - Build and run a test suite on every change (if "www/test.js" is a NodeJS file you have compiled)
 | 
						|
 | 
						|
Please note `npm run ...` also works just fine.
 | 
						|
 | 
						|
### Requiring files
 | 
						|
 | 
						|
Note: you must add `-lib haxe-loader` to your HXML to use the `Webpack` class.
 | 
						|
 | 
						|
#### Synchronous requires
 | 
						|
 | 
						|
To require 3rd party NPM modules, you can use `@:jsRequire` metadata or
 | 
						|
[`js.Lib.require()`](http://api.haxe.org/js/Lib.html#require).
 | 
						|
 | 
						|
However, those requires are relative to you HXML file!
 | 
						|
It also cannot be compiled on platforms other than JS.
 | 
						|
 | 
						|
It is thus recommended to call instead:
 | 
						|
 | 
						|
```haxe
 | 
						|
Webpack.require('./MyFile.css');    // requires a CSS file in the same directory as the current ".hx" file
 | 
						|
Webpack.require('../locales.json'); // requires a JSON file in the parent directory of the current ".hx" file
 | 
						|
```
 | 
						|
 | 
						|
It is silently ignored on non-JS targets.
 | 
						|
In future we may try to handle require statements for other targets.
 | 
						|
 | 
						|
#### Asynchronous requires (code splitting)
 | 
						|
 | 
						|
To leverage code splitting, you must use the `Webpack.load` require,
 | 
						|
and provide the Haxe module you want to load as a separate bundle:
 | 
						|
 | 
						|
```haxe
 | 
						|
import com.MyComponent;
 | 
						|
...
 | 
						|
Webpack.load(MyComponent).then(function(_){
 | 
						|
    var comp = new MyComponent();
 | 
						|
});
 | 
						|
```
 | 
						|
 | 
						|
Using this API, the Haxe compiler output will be processed and cut into separate files.
 | 
						|
 | 
						|
### Dev server setup
 | 
						|
 | 
						|
You can use [webpack-dev-server](https://webpack.js.org/configuration/dev-server/) to watch changes and auto-refresh a page after Haxe has compiled any changes.
 | 
						|
 | 
						|
Install `webpack-dev-server`
 | 
						|
 | 
						|
    yarn add --dev webpack-dev-server    # Or you can `npm install --dev webpack-dev-server`
 | 
						|
 | 
						|
Add some configuration to your `webpack.config.js`:
 | 
						|
 | 
						|
    devServer: {
 | 
						|
        contentBase: "./www",   // Your web root is in the "www" folder
 | 
						|
        publicPath: "/assets/", // The JS or assets webpack is building are in "www/assets"
 | 
						|
        overlay: true,          // Display compilation errors in the browser
 | 
						|
    },
 | 
						|
 | 
						|
Add a script to your `package.json`:
 | 
						|
 | 
						|
    "scripts": {
 | 
						|
        "start": "webpack-dev-server --open",
 | 
						|
    },
 | 
						|
 | 
						|
Run `yarn run start` to start the development server.
 | 
						|
 | 
						|
If you have a backend you want to use, for example Nekotools running on `http://localhost:2000`, webpack-dev-server comes with a proxy:
 | 
						|
 | 
						|
    devServer: {
 | 
						|
        contentBase: "./www", // The server will run from this directory
 | 
						|
        overlay: true, // If there are errors while rebuilding they will be overlayed on the page
 | 
						|
        proxy: { // Proxy all requests to localhost:2000
 | 
						|
            "/": {
 | 
						|
                changeOrigin: true,
 | 
						|
                target: "http://localhost:2000"
 | 
						|
            }
 | 
						|
        },
 | 
						|
        publicPath: "/js/" // Webpack assets are compiled to this folder, these will be intercepted by the dev server (and not proxied).
 | 
						|
    },
 | 
						|
 | 
						|
### Compiling non-JS assets
 | 
						|
 | 
						|
You can use Webpack and haxe-loader to compile all of your hxml files, not just those targeting client side Javascript.
 | 
						|
This way you can have webpack watch, rebuild and refresh your page for PHP, NodeJS, Neko etc.
 | 
						|
 | 
						|
When you use this option, Haxe will output the compilation files specified in your hxml file, but Webpack will still emit a JS bundle.
 | 
						|
For example, you might end up with a file named `php-server.bundle.js`.
 | 
						|
If you look inside, you'll realise that this file contains nothing other than some webpack boilerplate.
 | 
						|
You do not need to include this file as a script in your HTML.
 | 
						|
If you do however, webpack-dev-server will know to refresh the page every time the PHP files are rebuilt.
 | 
						|
 | 
						|
If you are using NodeJS as a server, and would like it to restart after a compilation, you can use "nodemon":
 | 
						|
 | 
						|
    nodemon server.js
 | 
						|
 | 
						|
Given that there will be a delay between Haxe finishing building "server.js" and nodemon restarting the server, you may wish to delay webpack refreshing the page.
 | 
						|
You can specify a delay in milliseconds using the "delayForNonJsBuilds" option:
 | 
						|
 | 
						|
```js
 | 
						|
    module: {
 | 
						|
        rules: [
 | 
						|
            {
 | 
						|
                test: /\.hxml$/,
 | 
						|
                use: [{ loader: 'haxe-loader', options: {delayForNonJsBuilds: 300} }],
 | 
						|
            },
 | 
						|
        ],
 | 
						|
    }
 | 
						|
```
 | 
						|
 | 
						|
### Contributing
 | 
						|
 | 
						|
Don't hesitate to create a pull request. Every contribution is appreciated.
 | 
						|
 | 
						|
## Maintainers
 | 
						|
 | 
						|
<table>
 | 
						|
  <tbody>
 | 
						|
    <tr>
 | 
						|
      <td align="center">
 | 
						|
        <a href="https://github.com/jasononeil">
 | 
						|
          <img width="150" height="150" src="https://github.com/jasononeil.png?v=3&s=150">
 | 
						|
          </br>
 | 
						|
          Jason O'Neil
 | 
						|
        </a>
 | 
						|
      </td>
 | 
						|
      <td align="center">
 | 
						|
        <a href="https://github.com/elsassph">
 | 
						|
          <img width="150" height="150" src="https://github.com/elsassph.png?v=3&s=150">
 | 
						|
          </br>
 | 
						|
          Philippe Elsass
 | 
						|
        </a>
 | 
						|
      </td>
 | 
						|
    </tr>
 | 
						|
  <tbody>
 | 
						|
</table>
 | 
						|
 | 
						|
### License
 | 
						|
 | 
						|
MIT
 |