npm package: @pilotlab/pilot-webpack
Description: Presets for setting up webpack with hotloading and TypeScript transpiling. Based on hjs-webpack by Henrik Joreteg.
Author: Pilot Lab
Latest version: 0.12.61

# pilot-webpack

---

Simplified Webpack setup and configuration:

- Installs as a Node package.
- Simple options with reasonable defaults, and no additional configuration for most projects.
- Organizes all Webpack-specific code into a separate repo.
- Automatically installs any needed dependencies like webpack, webpack-dev-server, middleware, and default loaders.
- Provides a simple CLI, that installs with the module, for build and dev commands.
  - `pwp build` and `pwp start`

## install

```
npm install --save @pilotlab/pilot-webpack
```

NOTE: Requires authentication to private repo

## Usage

#### Step 1. Create a webpack.config.js

Put it at the root of your project, and include the following line:

```js
module.exports = require('@pilotlab/pilot-webpack').configure();
```

#### Step 2. Add the following folders/files to your project

```text
src
└─┬ assets
  ├ index.ejs
  └ index.js
```
  
#### Step 3. Setup your index.ejs template

Include the follow code in the index.ejs file. Customize as necessary.

```html
<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
  <title><%= htmlWebpackPlugin.options.title %></title>
  <link rel="shortcut icon" href="<%= htmlWebpackPlugin.options.publicPath %>assets/fixtures/favicon/favicon.ico" type="image/x-icon">
</head>
<body>
<div id="app"></div>
</body>
</html>
```


#### Step 4. Generate your index.html


Run `./node_modules/.bin/pwp build`. By default, the build will generate your files into `public`, along with an `index.html` that automatically includes them.

You can run `./node_modules/.bin/pwp start` and open a browser to `http://localhost:8080`.

#### Step 5. Install any optional loaders that are needed for your project. 

See the list below.

#### Step 6. Override default options as necessary

`pilot-webpack` uses the following default options:

```js
{
    in: {
        //* Main dev directory, relative to project root.
        //* Expressed as './<folder name>/'.
        path: './src/',
        //* Main script input file name.
        script: 'index.js',
        //* Assets sub-folder name.
        assets: 'assets/'
    },
    //* Expressed in KB. Files below this size limit will
    //* be included as base64 data URL's.
    urlLoaderLimit: 10000,
    excludes: /(node_modules|bower_components|types|typings)/,
    styles: {
        //* See https://github.com/css-modules/css-modules
        isModules: true
    },
    production: {
        //* Info about build directory.
        out: {
            //* Main output directory path, relative to project root.
            path: './dist/',
            //* Relative public entry path.
            public: '/',
            //* Assets sub-folder name.
            assets: 'assets/',
            //* Scripts sub-folder name.
            scripts: 'scripts/',
            //* Name of main script.
            script: 'index.js',
            //* Styles sub-folder name.
            styles: 'styles/',
            //* Name of main css file.
            style: 'index.css',
            //* Main html file name.
            html: 'index.html'
        },
        docs: {
            //* Should we generate documentation?
            isDocs: false,
            //* Output directory for documentation files.
            path: './docs'
        },
        clean: {
            //* Should we clean out the output folder before building?
            isClean: true,
            //* Don't remove these files/folders.
            exclude: []
        }
    },
    development: {
        port: 8080,
        //* Working server path, relative to project root.
        public: '/',
        analyze: {
            isAnalyze: false,
            /**
             * Can be `server`, `static` or `disabled`.
             * In `server` mode analyzer will start HTTP server to show bundle report.
             * In `static` mode single HTML file with bundle report will be generated.
             * In `disabled` mode you can use this plugin to just generate Webpack Stats JSON file by setting `generateStatsFile` to `true`.
             */
            mode: 'server',
            //* Host that will be used in `server` mode to start HTTP server.
            host: '127.0.0.1',
            //* Port that will be used in `server` mode to start HTTP server.
            port: 8888,
            //* Path to bundle report file that will be generated in `static` mode.
            //* Relative to bundles output directory.
            report: 'report.html'
        }
    }
}
```

Any of these options can be overriden in the `wepback.config.js` file, as in the example below.

```js
module.exports = require('@pilotlab/pilot-webpack').configure({
  in: {
    path: './lib/',
    script: 'index.js'
  }
});
```

Or, override any webpack config defaults directly, using the 2nd parameter:

```js
module.exports = require('@pilotlab/pilot-webpack').configure({}, {
  output: {
    path: path.resolve('./build/'),
    filename: 'bundle.js'
  }
});
```

The default Webpack config looks like this:

```js
{
    entry: path.resolve(options.in.path + options.in.script),
    output: {
        path: path.resolve(options.production.out.path),
        publicPath: options.production.out.public,
        filename: options.production.out.assets + options.production.out.scripts + options.production.out.script
    },
    resolve: {
        extensions: ['.css', '.html', '.sass', '.scss', '.styl', '.ts', '.tsx', '.vue', 'vue.ts', '.js'],
        alias: {
            'vue$': 'vue/dist/vue.common.js'
        }
    },
    module: {
        rules: [
            {
                test: /\.html/,
                loader: 'raw-loader'
            },
            {
                test: /\.otf(\?\S*)?$/,
                loader: 'url-loader',
                options: {
                    limit: options.urlLoaderLimit
                }
            },
            {
                test: /\.eot(\?\S*)?$/,
                loader: 'url-loader',
                options: {
                    limit: options.urlLoaderLimit
                }
            },
            {
                test: /\.svg(\?\S*)?$/,
                loader: 'url-loader',
                options: {
                    mimetype: 'image/svg+xml',
                    limit: options.urlLoaderLimit
                }
            },
            {
                test: /\.ttf(\?\S*)?$/,
                loader: 'url-loader',
                options: {
                    mimetype: 'application/octet-stream',
                    limit: options.urlLoaderLimit
                }
            },
            {
                test: /\.woff2?(\?\S*)?$/,
                loader: 'url-loader',
                options: {
                    mimetype: 'application/font-woff',
                    limit: options.urlLoaderLimit
                }
            },
            {
                test: /\.(jpe?g|png|gif)$/,
                loader: 'url-loader',
                options: {
                    limit: options.urlLoaderLimit
                }
            }
        ]
    },
    performance: {
        hints: false
    },
    devServer: {
        //* contentBase and inline were added to tell dev-server to use
        //* the index.html file generated by html-webpack-plugin in the dist folder
        contentBase: options.production.out.path,
        inline: true,
        historyApiFallback: true,
        noInfo: true
    },
    devtool: '#cheap-eval-source-map'
}
```

### Changing PostCSS config

To customize PostCSS usage, place a file at the root of your project called `postcss.config.js` with the following format. See [bablerc docs](https://babeljs.io/docs/usage/babelrc/) for more options.

```js
module.exports = {
    plugins: [
        
    ]
};
```

### Changing Babel config

The easiest way to tweak Babel settings is to create a file at the root of your project called `.babelrc` that contains config settings. See [bablerc docs](https://babeljs.io/docs/usage/babelrc/) for more options.

If you're using the built-in webpack dev server, The following presets are helfpul for hot-loading. However, don't use them with the Express hot-loading setup.

```sh
npm install babel-preset-es2015 babel-preset-react babel-preset-react-hmre --save-dev
```

and then your `.babelrc`

```json
{
  "presets": ["es2015", "react"],
  "env": {
    "development": {
      "presets": ["react-hmre"]
    }
  }
}
```

## Pre-installed loaders

- All of the CSS loaders and plugins use [`css-loader`](https://www.npmjs.com/package/css-loader), [`postcss-loader`](https://www.npmjs.com/package/postcss-loader), and [`style-loader`](https://www.npmjs.com/package/style-loader), so those are pre-installed with the module.
- [`url-loader`](https://www.npmjs.com/package/url-loader) allows you to import assets that return a data url if the size is less than the [`urlLoaderLimit`](#urlloaderlimit-optional-number-default-10000). 
    - Extensions: `jpg jpeg png gif svg otf eot svg ttf woff`.

## Pre-installed plugins

- [`dotenv-webpack`](https://github.com/mrsteele/dotenv-webpack) allows you to include a `.env` file in your project to set environment variables, like `NODE_ENV=production`.

## Optional loaders

`pilot-webpack` relies on a number of optional dependencies to add functionality for things like Sass preprocessing, ES6 transpiling, TypeScript transpiling, templates, and plugins.

In order to get this additional functionality you should `npm install` the loaders and plugins you want `pilot-webpack` to use. If `pilot-webpack` detects that they are installed, then they will be used automatically without any further configuration.

Here's some more information about some of the available loaders and plugins and what they each do. You should install each that you want with `npm install --save-dev`.


#### CSS

- [`less-loader`](https://www.npmjs.com/package/less-loader) Require compiled less files. Extension: `less`.
- [`stylus-loader`](https://www.npmjs.com/package/stylus-loader) Require compiled stylus files. Extension: `styl`.
- [`sass-loader`](https://www.npmjs.com/package/sass-loader) Require compiled sass files using the regular or indented syntax. Extensions: `sass scss`.


#### JS/JSX

- [`babel-loader`](https://www.npmjs.com/package/babel-loader) Require transpiled JS with built-in support for ES2015 and JSX. Extensions: `js jsx babel`.
- [`coffee-loader`](https://www.npmjs.com/package/coffee-loader) Require CoffeeScript. Extension: `coffee`.
- [`ts-loader`]() Require TypeScript. Extensions: `ts` and `tsx`.
- [`vue-loader`]() Require TypeScript and av-ts. This also requires `ts-loader` to be installed. Extension: `vue` 
    - `pilot-webpack` will automatically append .ts extension to .vue files.


#### WebWorkers

- [`worker-loader`](https://www.npmjs.com/package/worker-loader) This lets us more easily write code for WebWorkers.


#### Templates

- [`nunjucks-loader`](https://github.com/at0g/nunjucks-loader) Require nunjucks files as compiled functions. Extension: `njk nunj nunjucks`.
- [`pug-loader`](https://www.npmjs.com/package/pug-loader) Require pug files as compiled functions. Extension: `pug` (legacy `jade` also supported).

## Optional plugins

- [`rupture`](https://www.npmjs.com/package/babel-loader)
- [`yeticss`](http://yeticss.com/)

# Hot-loading in Express

`pilot-webpack` has a built-in function that makes it easy to add hot-loading functionality when using a custom Express server. See the example below.
```
var config = require('./wepback.config.js');
var pwp = require('@pilotlab/pilot-webpack');
const express = require('express');

const app = express();

/// Other setup

/// we only want hot reloading in development
if (process.env.NODE_ENV !== 'production') {
  console.log('DEVOLOPMENT ENVIRONMENT: Turning on WebPack Middleware...');
  pwp.heatExpressApp(app, config);
} else {
  console.log('PRODUCTION ENVIRONMENT');
  /// Production needs physical files! (built via separate process)
  app.use(express.static(__dirname + '/public'));
}
```

## Credits

This package is based on Henrik Joreteg's hjs-webpack, migrated to Webpack 3, and customized to meet the needs of Pilot Lab.

## Changelog

See the [`CHANGELOG.md`](CHANGELOG.md)

## license

MIT