# @wjunt/webpack-config

Presets of webpack config.

## Install

Install package in project.

```shell
yarn add -D @wjunt/webpack-config webpack typescript
```

## Quick start

**`webpack.config.js`**

This package uses [ts-loader](https://www.npmjs.com/package/ts-loader) to transpile TypeScript and ES6+.

You can also use [babel-loader](https://www.npmjs.com/package/babel-loader) if you like. It's all up to you.

```js
const { merge, css, ts, vue } = require('@wjunt/webpack-config');

module.exports = merge(
    // Support css bundling.
    css(),
    
    // Support Vue SFC.
    vue(),
    
    // Transpile TypeScript and ES6+.
    ts({
        vue: true,
        exclude: /node_modules/,
    }),
    
    // You can configure webpack here.
    {
        externals: {
            'vue': 'Vue',
            'react': 'React',
            'react-dom': 'ReactDOM',
        },
    },
);
```

**`tsconfig.json`**

If you would like to use TypeScript, there is a common configuration for you to start quickly. 

```json
{
  "extends": "@wjunt/webpack-config/conf/tsconfig",
  "compilerOptions": {
    "jsx": "react"
  },
  "include": [
    "source"
  ]
}
```

*Note: `{ "jsx": "react" }` is necessary when you are coding with React.*

## Usage

Some examples of common projects.

### Vue

**`webpack.config.js`**

```js
const { merge, css, ts, vue } = require('@wjunt/webpack-config');

module.exports = merge(
    css(),
    vue(),
    ts({
        exclude: /node_modules/,
        feature: ['vue'],
    }),
    {
        externals: {
            'vue': 'Vue',
        },
    },
);
```

**`tsconfig.json`**

```json
{
  "extends": "@wjunt/webpack-config/conf/tsconfig",
  "include": [
    "source"
  ]
}
```

### React

**`webpack.config.js`**

```js
const { merge, css, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    css(),
    ts({
        exclude: /node_modules/,
        feature: ['react'],
    }),
    {
        externals: {
            'react': 'React',
            'react-dom': 'ReactDOM',
        },
    },
);
```

**`tsconfig.json`**

```json
{
  "extends": "@wjunt/webpack-config/conf/tsconfig",
  "include": [
    "source"
  ]
}
```

#### Tweak React components in real time

To enable React Component hot-reload and keep state unchanged, install [react-hot-loader](https://www.npmjs.com/package/react-hot-loader), then mark the root component as hot-updatable.

```jsx
import { render } from 'react-dom';
import { hot } from 'react-hot-loader/root';

const App = hot(() => (
    <div>
        Your components/routes here.
    </div>
));

render(<App/>, document.querySelector('#app'));
```

### Less

Install less-loader at first.

```shell
yarn add -D less-loader less
```

**`webpack.config.js`**

```js
const { merge, less, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    less(), // Test /\.less$/ by default.
    ts(),
);
```

And you can also simply use `css()` like this:

**`webpack.config.js`**

```js
const { merge, css, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    css({
        test: /\.(less|css)$/,
        'useAppend': ['@wjunt/less-loader'],
    }),
    ts(),
);
```

### Ant Design

Use [ts-import-plugin](https://www.npmjs.com/package/ts-import-plugin) to optimize bundling antd.

```shell
yarn add -D ts-import-plugin
```

**`webpack.config.js`**

```js
const { merge, css, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    css(),
    ts({
        exclude: /node_modules/,
        feature: [
            'react',
            'antd',
        ],
    }),
    {
        externals: {
            'react': 'React',
            'react-dom': 'ReactDOM',
        },
    },
);
```

`tsconfig.json` is the same as [React](#React).

Now it's time to code with antd.

```jsx
import React from 'react';
import { Button } from 'antd';

export const Component = () => {
    return (
        <div>
            <p>Hello world!</p>
            <Button>Bye~</Button>
        </div>
    );
};
```

### Control Statemens

Use [tsx-control-statements](https://www.npmjs.com/package/tsx-control-statements) to transform jsx control statements.

```shell
yarn add -D tsx-control-statements
```

**`webpack.config.js`**

```js
const { merge, css, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    css(),
    ts({
        exclude: /node_modules/,
        feature: [
            'react',
            'control-statements',
        ],
    }),
    {
        externals: {
            'react': 'React',
            'react-dom': 'ReactDOM',
        },
    },
);
```

**`tsconfig.json`**

```json
{
  "extends": "@wjunt/webpack-config/conf/tsconfig",
  "compilerOptions": {
    "jsx": "react"
  },
  "files": [
    "node_modules/tsx-control-statements/index.d.tsx"
  ],
  "include": [
    "source"
  ]
}
```

Now it's time to code with control statements.

```jsx
import React from 'react';
import { Button } from 'antd';

export const SongRelatedThingy = ({ songList }: { songList: string[] }) => (
    <p>
        <If condition={songList.includes('Gery-Nikol - Im the Queen')}>
            good taste in music
        </If>
    </p>
);
```

### Enable Hot Reload Manually

You can enable hot reload at specific entry/entries with `hotReload()` API.

**`webpack.config.js`**

```js
const { merge, ts, hotReload } = require('@wjunt/webpack-config');

module.exports = merge(
    ts(),
    {
        entry: {
            app: hotReload('./src/app.ts'),
        },
    },
);
```

### Split chunks

It's recommended to split common chunks when project grows. For example the dependencies in `node_modules`.

You can simply split all chunks in `node_modules` with `splitChunks()` API. All split chunks will be placed in `vendors.js` by default.

**`webpack.config.js`**

```js
const { merge, ts, splitChunks } = require('@wjunt/webpack-config');

module.exports = merge(
    ts(),
    splitChunks(), // With priority -10.
);
```

If you wanna change the output filename, try `splitChunks('lib')`, which places all split chunks in a file with the name you give.

It's also possible to set several cache groups. For example:

**`webpack.config.js`**

```js
const { merge, ts, splitChunks } = require('@wjunt/webpack-config');

module.exports = merge(
    ts(),
    splitChunks(),
    splitChunks({
        name: 'react',
        chunks: 'initial',
        test: /node_modules\/react/,
    }),
);
```

This configuration places all chunks related to react in `react.js`, while others in `vendors.js`.

### Exclude node_modules

Mostly it's unnecessary to transpile files in `node_modules`.

**`webpack.config.js`**

```js
const { merge, ts } = require('@wjunt/webpack-config');

module.exports = merge(
    // Same as webpack rule spec.
    ts({
        exclude: /node_modules/,
    }),
);
```

---

*To be continued...*

