从零构建活动项目webpack4配置(一)

最近在做互动开发,因为是全新的域名和新的产品,原先的活动开发体系也就不能用了。借此机会我也刚好借此用webpack 4.X来重新搭建一个活动开发的项目,顺便把自己的想法实践一下。

活动项目的特点

运营类的活动比较多,而且相互之间的关系并不大,因此往往我们会按照年份和不同的产品进行目录划分。

同时每个活动会用一个单独的文件夹作为入口,一则方便代码管理,二则也同时确定了活动的访问路径。

原先的运营活动PC端和WAP端页面是分放在PCWAP两个大的分类下的,下面再按照年份和产品进行了区分。这里有一个问题就是:很多活动都是同时有PCWAP的,两者主题的业务逻辑是一样的,不同的只有展示效果和部分交互逻辑,分放两份的话一来代码重复,而来修改问题时同时要改两个部分,这其实还是不够方便的。

因此我最终的目录划分确定为:

每个活动目录下都会有一个template目录来放置重构文件,我们开发的业务逻辑将全部放置到src下,这样我们业务代码和重构代码就完全分离开了。每当重构文件有更新的时候,配合上公司同事开发的重构文件同步插件就能一键完成重构文件更新,同时不会影响到我们的业务代码。

空项目创建

第一步常规操作:

1
npm init -y

初始化项目后,我们首先要安装的就是webpack,现在4.X版本webpack-cli已经独立出来了,要单独安装:
yarn add -D webpack webpack-cli

在安装好这两个依赖之后,其实我们就可以跑起来了:

1
2
3
4
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}

webpack4中加入了mode配置项,它值有developmentproduction两种,分别表示开发环境和运行环境。运行上面两个终端命令就能立马可以开始开发了。

当然现在这是默认的零配置开发,默认的入口文件是src/index.js。而我们的目录结构不是这样的,并且开发环境我们肯定是需要webpack-dev-server来启动服务和热更新的。因此我们需要写自己的自定义配置来满足我们的需求。

配置文件

以下是配置只写了主要内容,有些东西省略了:

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
......
const isProd = process.env.NODE_ENV === 'production'
// 这里是用来确定当前活动需要做哪些平台
const entries = (function(platform) {
if (platform === 'all') return ['pc', 'wap']
return [platform]
}(process.env.platform))

module.exports = {
// 根据传入的环境变量来确定mode值
mode: isProd ? 'production' : 'development',
// 根据要做平台来指定入口文件
entry: entries.reduce((p, c) => {
p[c] = `./src/${c}/index.js`
return p
}, {}),
output: {
path: path.resolve(__dirname, './dist'),
filename: isProd ? '[name]/build.[chunkHash:8].js' : '[name]/build.js'
},
module: {
rules: [...]
},
plugins: [
// 根据要做平台来生成活动页面
...entries.map(e => {
return new HtmlWebpackPlugin({
filename: `./${e}/index.html`,
template: `./template/${e}/index.html`,
inject: true,
chunks: [e]
})
}),
],
devServer: {
port: 80, // 在Mac上如果端口号小于1024,就需要用管理员权限启动项目
disableHostCheck: true, // 开发时如果将网址host改为127.0.0.1,需要将该配置项设为true
......
},
......
};

此时在控制台输入

cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js

项目启动之后,我们通过浏览器访问localhost/pc,会发现我们的页面上所有的文件加载都报404。我们查看控制台可以发现所有的文件加载路径全部都相对于我们项目根路径去了,这样自然就加载不到文件。

那问题就来了,我们不可能去修改重构稿里每个资源引用的路径。又因为存在两个平台的活动同时开发的情况,所以修改服务器启动的contentBase也不是一个好的选择。

这个时候我考虑一种情况就是:我们在发布活动时,会将文件全部都打包到当前项目的dist文件夹下,重构用到的所有的资源也都会拷贝到dist目录下,那是不是可以在开发态时也将文件拷贝到dist下,这样访问时也刚好和生产环境是一样的路径。于是我在plugins下加上了拷贝文件的插件:

1
2
3
4
5
6
new CopyWebpackPlugin(entries.map(e => {
return {
// 因为输出文件夹指向的是dist,所以to这里就根路径就是dist了
from: `./template/${e}/`, to: `./${e}/`, force: true, toType: 'dir', ignore: ['index.js', '*.html', '*.tpl']
}
})),

这个时候我们再运行启动开发环境,却发现项目下并不会生成dist文件夹,拷贝动作根本没有生效。我们都知道启动webpack-dev-server之后,我们的HTML和生成的JS文件都是存储在内存中的,同理开发态下CopyWebpackPlugin把文件也都拷贝到内存中去了,我们在资源访问路径中加入pc|wap文件夹路径就能访问到了。但这样一来还是不能解决我的问题。于是我就开始了寻找,最终我在
copy-webpack-plugin
描述中看到这样一句话:

If you want webpack-dev-server to write files to the output directory during development, you can force it with the write-file-webpack-plugin.

就是说如果我们用webpack-dev-server启动项目后,如果想把文件从内存写入到我们的output文件夹,我们可以通过
write-file-webpack-plugin
这个插件来实现。

于是当我在plugins中加上:

1
new WriteFilePlugin()

启动开发环境,项目中如期的写入了dist文件夹,所有的重构文件、原本在内存中的HTML和build.js都出现了。这个时候访问localhost/dist/pc就能正常访问了。

npm script 改造

完成了配置文件的编写之后,我们回过头来看看package.json中的scripts

1
2
3
"scripts": {
"dev": "cross-env NODE_ENV=development platform=pc webpack-dev-server --config webpack.config.js"
}

我们是通过cross-env来对NODE_ENVplatform的值进行设置的,这样语句就变得很长不方便查看和维护。
这里我推荐用better-npm-run来优化一下书写体验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"script": {
"dev:pc": "better-npm-run dev:pc",
"build:pc": "better-npm-run build:pc",
},
"betterScripts": {
"dev:pc": {
"command": "webpack-dev-server --config webpack.config.js",
"env": {
"NODE_ENV": "development",
"platform": "pc" // 这个参数我们用来在配置文件中进行入口判断
}
},
"build:pc": {
"command": "webpack --config webpack.config.js --progress --hide-modules",
"env": {
"NODE_ENV": "production",
"platform": "pc"
}
},
}

这样一来我们可以列举3种情况来区分执行不同的开发和打包命令了。

0%