一、准备工作
在终端输入:
> mkdir webpack_demo
> cd webpack_demo
> mkdir src
> mkdir dist
> npm init -y
> sudo npm install webpack webpack-cli --save-dev
> sudo npm install --save-dev html-webpack-plugin
> sudo npm install clean-webpack-plugin --save-dev
> sudo npm install --save-dev webpack-dev-server
> sudo npm install uglifyjs-webpack-plugin
> sudo npm install --save-dev style-loader css-loader
> sudo npm install --save-dev file-loader
> sudo npm install --save-dev csv-loader xml-loader
目录结构:
package.json:
{
"name": "webpack_dome",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --open",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^1.0.0",
"css-loader": "^2.1.0",
"csv-loader": "^3.0.2",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"style-loader": "^0.23.1",
"webpack": "^4.28.4",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14",
"xml-loader": "^1.2.1"
}
}
webpack.config.js:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
module.exports={
entry:{
app: './src/entry.js'
},
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title:'Output Management'
}),
new UglifyJSPlugin()
],
output:{
filename: '[name].bundle.js',
path:path.resolve(__dirname,'dist'),
},
}
src/entry.js:
function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello webpack';
return element;
}
document.body.appendChild(component());
运行:
> npm start
若出现像这样的报错
Cannot find什么模块,我们就安装什么模块,
这里我们安装uri-js模块,在终端输入:
> sudo npm install --save-dev uri-js
再重新npm start一下,看看有没有问题~
二、重构项目
开发环境(development)和生产环境(production)的构建目标差异很大。
- 在开发环境中,我们需要具有实时重新加载 或 热模块替换能力的 source map 和 localhost server。
- 在生产环境中,我们的目标则转向于关注更小的 bundle,更轻量的 source map,以及更优化的资源,以改善加载时间。
由于要遵循逻辑分离,我们通常建议为每个环境编写彼此独立的 webpack 配置:开发环境、生产环境各有一个不同的配置。然后遵循不重复原则:保留一个“通用”配置。
为了将这些配置合并在一起,我们将使用一个名为 webpack-merge 的工具。通过“通用”配置,我们不必在环境特定的配置中重复代码。
接着上面的准备工作,
1、分离代码
重构后的目录结构:
安装 webpack-merge :
> sudo npm install --save-dev webpack-merge
webpack.common.js:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/entry.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
webpack.dev.js:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
});
webpack.prod.js:
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
})
]
});
- webpack.common.js 中,我们设置了 entry 和 output 配置,并且在其中引入这两个环境公用的全部插件。
- webpack.dev.js 中,我们为此环境添加了推荐的 devtool(强大的 source map)和简单的 devServer 配置。
- webpack.prod.js 中,我们引入了UglifyJSPlugin。然后启用了 source map,因为它有利于调试源码(debug)和运行基准测试。这里我们使用 source-map 选项,而不是在开发环境中用到的 inline-source-map
避免在生产中使用 inline-*** 和 eval-***,因为它们可以增加 bundle 大小,并降低整体性能。
2、NPM Scripts
现在,我们把 scripts 重新指向到新配置。
- npm start 定义为 开发环境 脚本,并在其中使用 webpack-dev-server
- npm run build 定义为 生产环境 脚本:
注:npm start后,dist文件夹会消失;npm run build后,dist文件夹又会出现
package.json:
{
"name": "webpack_dome",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"clean-webpack-plugin": "^1.0.0",
"fast-deep-equal": "^2.0.1",
"fast-json-stable-stringify": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2",
"webpack": "^4.28.4",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14",
"webpack-merge": "^4.2.1"
}
}
三、指定环境
许多 library 将通过与 process.env.NODE_ENV 环境变量关联,以决定 library 中应该引用哪些内容。例如,当不处于生产环境中时,某些 library 为了使调试变得容易,可能会添加额外的日志记录(log)和测试(test)。其实,当使用 process.env.NODE_ENV === ‘production’ 时,一些 library 可能针对具体用户的环境进行代码优化,从而删除或添加一些重要代码。我们可以使用 webpack 内置的 DefinePlugin 为所有的依赖定义这个变量:
webpack.prod.js:
const 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')
})
]
});
技术上讲,NODE_ENV 是一个由 Node.js 暴露给执行脚本的系统环境变量。通常用于决定在开发环境与生产环境(dev-vs-prod)下,服务器工具、构建脚本和客户端 library 的行为。然而,与预期不同的是,无法在构建脚本 webpack.config.js 中,将 process.env.NODE_ENV 设置为 “production”,请查看 #2537。因此,例如 process.env.NODE_ENV === ‘production’ ? ‘[name].[hash].bundle.js’ : ‘[name].bundle.js’ 这样的条件语句,在 webpack 配置文件中,无法按照预期运行。
如果你正在使用像 react 这样的 library,那么在添加此 DefinePlugin 插件后,你应该看到 bundle 大小显著下降。还要注意,任何位于 /src 的本地代码都可以关联到 process.env.NODE_ENV 环境变量,所以以下检查也是有效的:
src/entry.js:
if (process.env.NODE_ENV !== 'production') {
console.log('Looks like we are in development mode!');
}
function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello webpack';
return element;
}
document.body.appendChild(component());