使用webpack2.x构建项目

Webpack 是目前最流行的前端模块打包工具,它可以将 JavaScript、CSS、图片等各种资源视为模块,通过 loader 和 plugin 进行处理,最终打包成浏览器可识别的静态资源。

Webpack 2.x 是一个重要的里程碑版本,相比 1.x 带来了原生 ES6 模块支持、Tree Shaking、配置简化、性能提升等诸多改进。本文将详细介绍如何使用 Webpack 2.x 从零构建一个前端项目,涵盖基础配置、常用 loader/plugin、开发环境、生产环境优化等内容。


一、Webpack 2.x 核心新特性

先了解一下 2.x 相比 1.x 的关键变化,方便后续配置:

  1. 原生 ES6 模块支持:无需额外配置即可识别 import/export,为 Tree Shaking 提供基础;
  2. Tree Shaking:可以“摇掉”未使用的代码,减少打包体积(仅支持 ES6 模块);
  3. 配置简化module.loaders 改为 module.rulesresolve.extensions 不再需要空字符串;
  4. 性能提升:构建速度更快,打包体积更小;
  5. 更好的代码分割CommonsChunkPlugin 优化,支持更灵活的公共代码提取。

二、前置准备:环境安装

1. 安装 Node.js 和 npm

Webpack 基于 Node.js 运行,首先需要安装 Node.js(建议使用 LTS 版本),安装后 npm 会自动安装。

1
2
3
4
# 检查 Node.js 版本(建议 v6.x 及以上)
node -v
# 检查 npm 版本
npm -v

2. 初始化项目

创建一个新目录,进入目录后初始化 npm 项目:

1
2
mkdir webpack2-demo && cd webpack2-demo
npm init -y # -y 表示使用默认配置,快速生成 package.json

三、基础配置:从零开始

1. 安装 Webpack

1
2
# 安装 Webpack 2.x(指定版本,避免自动安装到 3.x+)
npm install webpack@2.x --save-dev

2. 创建项目结构

先搭建一个基础的项目目录:

1
2
3
4
5
6
7
8
webpack2-demo/
├── src/ # 源代码目录
│ ├── index.js # 入口文件
│ ├── module.js # 示例模块
│ └── index.css # 示例样式
├── index.html # HTML 模板
├── webpack.config.js # Webpack 配置文件
└── package.json

3. 编写基础代码

先写几个简单的文件,方便后续测试:

src/module.js

1
2
3
4
5
6
7
8
9
// 示例模块:导出一个函数
export function sayHello(name) {
return `Hello, ${name}!`;
}

// 未使用的函数(Tree Shaking 会摇掉)
export function unusedFunction() {
return 'This function is not used';
}

src/index.js

1
2
3
4
5
6
7
8
9
10
11
12
// 入口文件:引入模块和样式
import { sayHello } from './module.js';
import './index.css';

// 使用模块
const message = sayHello('Webpack 2.x');
console.log(message);

// 在页面上显示
const app = document.createElement('div');
app.textContent = message;
document.body.appendChild(app);

src/index.css

1
2
3
4
5
6
7
8
body {
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
div {
padding: 20px;
color: #333;
}

index.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Webpack 2.x Demo</title>
</head>
<body>
<!-- Webpack 会自动将打包后的 JS 插入这里 -->
</body>
</html>

4. 编写 Webpack 配置文件

在项目根目录创建 webpack.config.js,这是 Webpack 的核心配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const path = require('path');

module.exports = {
// 入口文件:Webpack 从这里开始构建依赖图
entry: './src/index.js',

// 输出配置:打包后的文件存放位置
output: {
filename: 'bundle.js', // 打包后的文件名
path: path.resolve(__dirname, 'dist') // 打包后的目录(必须是绝对路径)
},

// 模块配置:处理各种非 JS 文件
module: {
rules: [
// 这里后续会添加 loader 配置
]
},

// 插件配置:执行更广泛的任务(打包优化、资源管理等)
plugins: [
// 这里后续会添加 plugin 配置
],

// 解析配置:模块如何被解析
resolve: {
// 自动解析的扩展名:引入文件时可以省略这些后缀
extensions: ['.js', '.json', '.css']
}
};

5. 配置 npm scripts

package.json 中添加打包命令:

1
2
3
4
5
{
"scripts": {
"build": "webpack --config webpack.config.js"
}
}

现在执行 npm run build,Webpack 会开始打包,但因为还没配置 loader,CSS 文件会报错,接下来我们添加常用的 loader。


四、常用 Loader 配置:处理各种资源

Loader 用于将非 JS 文件转换为 Webpack 可识别的模块,以下是最常用的几个 loader。

1. 处理 CSS:style-loader、css-loader

1
2
# 安装 loader
npm install style-loader css-loader --save-dev

webpack.config.jsmodule.rules 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
module: {
rules: [
{
test: /\.css$/, // 匹配 .css 文件
use: [
'style-loader', // 将 CSS 插入到 HTML 的 <style> 标签中
'css-loader' // 解析 CSS 中的 @import 和 url()
]
// 注意:loader 执行顺序是从右到左(先 css-loader,再 style-loader)
}
]
}

2. 转译 ES6+:babel-loader

Webpack 2.x 支持 ES6 模块,但为了兼容旧浏览器(如 IE),还需要用 Babel 转译 ES6+ 语法。

1
2
# 安装 babel 相关依赖(注意版本匹配:babel-loader 7.x 对应 Webpack 2.x)
npm install babel-loader@7.x babel-core@6.x babel-preset-env@1.x --save-dev

在项目根目录创建 Babel 配置文件 .babelrc

1
2
3
4
5
6
7
8
9
10
{
"presets": [
["env", {
"modules": false, // 关键:关闭 Babel 的模块转换,保留 ES6 模块,让 Webpack 处理(用于 Tree Shaking)
"targets": {
"browsers": ["> 1%", "last 2 versions", "ie >= 9"] // 兼容的浏览器
}
}]
]
}

webpack.config.jsmodule.rules 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
module: {
rules: [
// ... 之前的 css loader
{
test: /\.js$/, // 匹配 .js 文件
exclude: /node_modules/, // 排除 node_modules 目录,提升构建速度
use: {
loader: 'babel-loader'
}
}
]
}

3. 处理图片/字体:file-loader、url-loader

1
2
# 安装 loader
npm install file-loader url-loader --save-dev

webpack.config.jsmodule.rules 中添加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
module: {
rules: [
// ... 之前的 loader
{
test: /\.(png|jpg|gif|svg)$/, // 匹配图片文件
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8kb 的图片转成 base64 嵌入 JS,大于 8kb 的用 file-loader 生成文件
name: 'images/[name].[hash:8].[ext]' // 输出文件名:带 8 位 hash,避免缓存
}
}
]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/, // 匹配字体文件
use: [
{
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
]
}
]
}

五、常用 Plugin 配置:增强构建功能

Plugin 用于执行更广泛的任务,比如生成 HTML、清理目录、提取 CSS 等。

1. 生成 HTML:html-webpack-plugin

自动生成 HTML 文件,并将打包后的 JS/CSS 自动插入。

1
2
# 安装 plugin
npm install html-webpack-plugin@2.x --save-dev

webpack.config.js 中配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
// ... 其他配置
plugins: [
new HtmlWebpackPlugin({
template: './index.html', // 模板文件
filename: 'index.html', // 输出文件名
inject: true, // 自动插入资源
minify: {
collapseWhitespace: true // 压缩 HTML(生产环境用)
}
})
]
};

2. 清理 dist 目录:clean-webpack-plugin

每次打包前自动清理 dist 目录,避免旧文件残留。

1
2
# 安装 plugin
npm install clean-webpack-plugin@0.x --save-dev

webpack.config.js 中配置:

1
2
3
4
5
6
7
8
9
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
// ... 其他配置
plugins: [
new CleanWebpackPlugin(['dist']), // 清理 dist 目录
// ... 其他 plugin
]
};

3. 提取 CSS 到单独文件:extract-text-webpack-plugin

默认情况下 CSS 会被 style-loader 插入到 <style> 标签中,生产环境建议提取到单独的 .css 文件。

1
2
# 安装 plugin(注意版本:2.x 对应 Webpack 2.x)
npm install extract-text-webpack-plugin@2.x --save-dev

修改 webpack.config.js 中的 CSS loader 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader', // 提取失败时回退到 style-loader
use: 'css-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin('css/[name].[contenthash:8].css'), // 输出 CSS 文件
// ... 其他 plugin
]
};

六、开发环境配置:提升开发体验

1. 配置 webpack-dev-server

提供一个本地开发服务器,支持热模块替换(HMR)、自动刷新、代理等功能。

1
2
# 安装 webpack-dev-server(2.x 版本)
npm install webpack-dev-server@2.x --save-dev

webpack.config.js 中添加开发服务器配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
module.exports = {
// ... 其他配置
devServer: {
contentBase: './dist', // 服务器根目录
hot: true, // 开启热模块替换
open: true, // 自动打开浏览器
port: 8080, // 端口号
proxy: { // 代理配置(解决跨域)
'/api': {
target: 'http://localhost:3000',
changeOrigin: true
}
}
},
// 配置 source map:方便调试(开发环境用 cheap-module-eval-source-map,速度快)
devtool: 'cheap-module-eval-source-map'
};

package.json 中添加开发命令:

1
2
3
4
5
6
{
"scripts": {
"dev": "webpack-dev-server --config webpack.config.js",
"build": "webpack --config webpack.config.js"
}
}

现在执行 npm run dev,Webpack 会自动启动开发服务器,打开浏览器,修改代码后会自动刷新。

2. 开启热模块替换(HMR)

webpack.config.js 中添加 HMR 插件:

1
2
3
4
5
6
7
8
const webpack = require('webpack');

module.exports = {
plugins: [
new webpack.HotModuleReplacementPlugin(), // HMR 插件
// ... 其他 plugin
]
};

七、生产环境优化:减小体积、提升性能

生产环境需要重点关注打包体积加载速度,以下是关键优化配置。

1. 区分开发/生产环境

创建两个配置文件:webpack.dev.js(开发环境)和 webpack.prod.js(生产环境),或者用 webpack-merge 合并公共配置。这里简化处理,直接修改 webpack.config.js,通过环境变量区分。

修改 package.json 的 scripts:

1
2
3
4
5
6
{
"scripts": {
"dev": "webpack-dev-server --env.dev --config webpack.config.js",
"build": "webpack --env.prod --config webpack.config.js"
}
}

修改 webpack.config.js,接收环境变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
module.exports = function(env) {
const isProd = env && env.prod;

return {
// ... 其他配置
devtool: isProd ? 'source-map' : 'cheap-module-eval-source-map', // 生产环境用 source-map
plugins: [
// ... 其他 plugin
// 生产环境添加压缩插件
isProd && new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
})
].filter(Boolean) // 过滤掉 false
};
};

2. 开启 Tree Shaking

Tree Shaking 可以删除未使用的代码,前提是:

  1. 使用 ES6 模块(import/export);
  2. Babel 配置中关闭模块转换("modules": false,之前已经配置过);
  3. 生产环境开启压缩(UglifyJsPlugin 会删除未使用的代码)。

package.json 中添加 sideEffects,告诉 Webpack 哪些文件有副作用(不能随便删):

1
2
3
4
5
{
"sideEffects": [
"*.css" // CSS 文件有副作用,不能删
]
}

3. 代码分割:提取公共代码

使用 CommonsChunkPlugin 提取公共代码(如 vendor 库、公共模块),减少重复打包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module.exports = function(env) {
return {
entry: {
main: './src/index.js', // 主入口
vendor: ['lodash'] // 第三方库入口(示例用 lodash,需先安装)
},
output: {
filename: '[name].[chunkhash:8].js', // 输出文件名带 chunkhash,用于缓存
path: path.resolve(__dirname, 'dist')
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor', // 提取 vendor 库
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest' // 提取 webpack 运行时代码,避免 vendor hash 变化
})
]
};
};

八、完整项目结构与配置示例

最后,整理一下完整的配置和项目结构,方便直接参考:

项目结构

1
2
3
4
5
6
7
8
9
webpack2-demo/
├── src/
│ ├── index.js
│ ├── module.js
│ └── index.css
├── index.html
├── webpack.config.js
├── .babelrc
└── package.json

完整 webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = function(env) {
const isProd = env && env.prod;

return {
entry: {
main: './src/index.js'
},
output: {
filename: isProd ? '[name].[chunkhash:8].js' : '[name].js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.css$/,
use: isProd
? ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
: ['style-loader', 'css-loader']
},
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.(png|jpg|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192,
name: 'images/[name].[hash:8].[ext]'
}
}
]
}
]
},
resolve: {
extensions: ['.js', '.json', '.css']
},
devtool: isProd ? 'source-map' : 'cheap-module-eval-source-map',
devServer: {
contentBase: './dist',
hot: true,
open: true,
port: 8080
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
template: './index.html',
inject: true,
minify: isProd ? { collapseWhitespace: true } : false
}),
isProd && new ExtractTextPlugin('css/[name].[contenthash:8].css'),
isProd && new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: { warnings: false }
}),
!isProd && new webpack.HotModuleReplacementPlugin()
].filter(Boolean)
};
};

九、常见问题与注意事项

  1. Loader 版本匹配:Webpack 2.x 对应的 loader/plugin 版本可能较老,安装时注意指定版本(如 babel-loader@7.x),否则可能报错。
  2. Tree Shaking 不生效:检查是否使用了 ES6 模块,Babel 是否配置了 modules: false,是否开启了生产环境压缩。
  3. 缓存问题:生产环境文件名带 hash,避免浏览器缓存旧文件;manifest 文件提取 webpack 运行时代码,避免 vendor hash 随业务代码变化。
  4. 性能优化:开发环境用 cheap-module-eval-source-map 提升构建速度,生产环境用 source-map 方便调试。

十、总结

Webpack 2.x 相比 1.x 有了很大的改进,配置更简洁,性能更好,Tree Shaking 和原生 ES6 模块支持是最大的亮点。掌握本文的内容,已经可以用 Webpack 2.x 构建一个完整的前端项目了。

虽然现在 Webpack 已经迭代到 5.x,但 2.x 的核心思想(入口、输出、loader、plugin)是一致的,学习 2.x 也能为后续学习新版本打下基础。


使用webpack2.x构建项目
https://cszy.top/2017-07-17 使用webpack2-x构建项目/
作者
csorz
发布于
2017年7月17日
许可协议