安装
1 | $ mkdir webpack-demo && cd webpack-demo |
lodash
1 | import _ from 'lodash'; |
1 | <html> |
1 | # npx webpack 等于 ./node_modules/.bin/webpack |
Loading CSS
1 | $ npm install --save-dev style-loader css-loader |
1 | module.exports = { |
Loading Images、Fonts
优化、压缩图片(image-webpack-loader、url-loader)
1 | $ npm install --save-dev file-loader |
1 | import Icon from './beauty.jpg'; |
Loading Data
1 | $ npm install --save-dev csv-loader xml-loader |
1 | import Data from './data.xml'; |
html-webpack-plugin
为了解决打包后 index.html 需要经常改变的问题1
$ npm install --save-dev html-webpack-plugin
1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); |
clean-webpack-plugin
清理 /dist 目录1
$ npm install --save-dev clean-webpack-plugin
1 | const CleanWebpackPlugin = require('clean-webpack-plugin'); |
Using source maps
1 | module.exports = { |
Choosing a Development Tool
1、webpack’s Watch Mode
缺点是要刷新1
2
3
4
5{
"scripts": {
"watch": "webpack --watch"
}
}
1 | $ npm run watch |
2、webpack-dev-server1
$ npm install --save-dev webpack-dev-server
package.json1
2
3
4
5{
"scripts": {
"start": "webpack-dev-server --open"
}
}
webpack.config.js1
2
3
4
5module.exports = {
devServer: {
contentBase: './dist'
}
};
1 | $ npm start |
3、webpack-dev-middleware
从 express 中启动调试,缺点要刷新1
$ npm install --save-dev express webpack-dev-middleware
package.json1
2
3
4
5{
"scripts": {
"server": "node server.js"
}
}
webpack.config.js1
2
3
4
5module.exports = {
output: {
publicPath: '/'
}
};
server.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath
}));
// Serve the files on port 3000.
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
1 | $ npm run server |
HMR
可能不起效,解决办法更新全局 webpack-dev-server
webpack.config.js1
2
3
4
5
6
7
8
9
10module.exports = {
devServer: {
contentBase: './dist',
hot: true
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};
index.js1
2
3
4
5
6if (module.hot) {
module.hot.accept('./print.js', function () {
console.log('Accepting the updated printMe module!');
printMe();
})
}
HRM Via the Node.js API
webpack.config.js 去掉 devServer 选项
server.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17const webpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('./webpack.config.js');
const options = {
contentBase: './dist',
hot: true,
host: 'localhost'
};
webpackDevServer.addDevServerEntrypoints(config, options);
const compiler = webpack(config);
const server = new webpackDevServer(compiler, options);
server.listen(5000, 'localhost', () => {
console.log('dev server listening on port 5000');
});
HMR with Stylesheets
1 | $ npm install --save-dev style-loader css-loader |
webpack.config.js1
2
3
4
5
6
7
8
9
10module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
Tree Shaking
1 | $ npm install --save-dev uglifyjs-webpack-plugin |
uglifyjs-webpack-plugin 替代方案
BabelMinifyWebpackPlugin
ClosureCompilerPlugin
webpack.config.js1
2
3
4
5
6const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
plugins: [
new UglifyJSPlugin()
]
};
webpack-merge
1 | $ npm install --save-dev webpack-merge |
webpack.common.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
webpack.dev.js1
2
3
4
5
6
7
8
9const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});
webpack.prod.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const webpack = require('webpack');
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'source-map',
plugins: [
new UglifyJSPlugin({
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
});
Specify the Environment
注意 webpack.config.js 中不能判断 process.env.NODE_ENV === ‘production’
webpack.prod.js1
2
3
4
5
6
7module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
};
index.js1
2
3if (process.env.NODE_ENV !== 'production') {
console.log('Looks like we are in development mode!');
}
Code Splitting
1、Entry Points: Manually split code using entry configuration.
缺点:各个 bundle 之间存在重复代码
2、revent Duplication: Use the CommonsChunkPlugin to dedupe and split chunks.
用 CommonsChunkPlugin 解决
webpack.config.js1
2
3
4
5
6
7module.exports = {
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common' // Specify the common bundle's name.
})
]
};
3、Dynamic Imports: Split code via inline function calls within modules.
webpack.config.js1
2
3
4
5module.exports = {
output: {
chunkFilename: '[name].bundle.js'
}
};
index.js1
2
3
4
5
6
7
8
9
10
11
12function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello world';
element.onclick = function () {
import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {
// Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
}).catch(error => 'An error occurred while loading the component');
};
return element;
}
document.body.appendChild(component());
Caching
两种产生唯一 chunkhash 的方式:NamedModulesPlugin(开发环境,易读) 和
HashedModuleIdsPlugin(效率更高)
webpack.config.js1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21module.exports = {
entry: {
main: './src/index.js',
vendor: [ // 第三方包单独打成一个包
'lodash'
]
},
plugins: [
new webpack.HashedModuleIdsPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor'
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' // 项目信息?
})
],
output: {
filename: '[name].[chunkhash].js', // 使用 chunkhash 而不是 hash
path: path.resolve(__dirname, 'dist')
}
};
Shimming
全局变量1
2
3
4
5
6
7module.exports = {
plugins: [
new webpack.ProvidePlugin({
join: ['lodash', 'join']
})
]
};
全局 this 指向 window,会导致 index.js 的 import 报错1
$ npm install --save-dev imports-loader
1 | module.exports = { |
导入非 ES5 模块,使用 exports-loader1
$ npm install --save-dev exports-loader
1 | module.exports = { |
Loading Polyfills
1 | $ npm install --save babel-polyfill |
webpack.config.js1
2
3
4
5
6
7
8
9
10module.exports = {
entry: {
polyfills: './src/polyfills.js',
index: './src/index.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
Work offline
1 | $ npm install workbox-webpack-plugin --save-dev |
webpack.config.js1
2
3
4
5
6
7
8
9
10module.exports = {
plugins: [
new WorkboxPlugin({
// these options encourage the ServiceWorkers to get in there fast
// and not allow any straggling "old" SWs to hang around
clientsClaim: true,
skipWaiting: true
})
]
};
index.js1
2
3
4
5
6
7
8
9if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js').then(registration => {
console.log('SW registered: ', registration);
}).catch(registrationError => {
console.log('SW registration failed: ', registrationError);
});
});
}
Environment Variables
webpack.config.js1
2
3
4
5
6
7
8
9
10
11
12
13module.exports = env => {
// Use env.<YOUR VARIABLE> here:
console.log('NODE_ENV: ', env.NODE_ENV) // 'local'
console.log('Production: ', env.production) // true
return {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
}
1 | $ webpack --env.NODE_ENV=local --env.production --progress |