现在,前端工程化越来越成为前端开发中不可回避的问题,伴随的还有模块化,组件化等。

那么,前端自动化工程主要解决一下一些问题:

  • JavaScript、css代码合并和压缩
  • css预处理语言的编译
  • 生成雪碧图
  • ES6转ES5
  • 模块化

虽然webpack看起来比较复杂,但它只不过是一个js配置文件,只需要搞清楚入口(Entry)、出口(Output)、加载器(Loaders)和插件(Plugins)这四个概念,使用起来就很容易了。

以下罗列了webpack搭载vue配置时一些常见的报错及处理方式,本次使用的webpack版本为4.19.0,请务必先安装node.js。

使用npm init初始化配置。

在项目目录下局部安装webpacknpm install webpack --save-dev

安装webpack服务,启动热更新npm install webpack-dev-server --save-dev,在package.json的scripts里面配置启动服务脚本,运行npm run dev会自动打开服务。

1
2
3
4
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --config webpack.config.js"
},

在项目目录下新建一个main.js文件作为入口文件,然后在webpack.config.js中配置。

1
2
3
4
5
6
7
8
9
10
11
12
var path = require('path');
var config = {
entry: {
main: './main' //入口文件
},
output: {
path: path.join(__dirname, './dist'), //输出文件路径
publicPath: '/dist/', //指定资源文件引用目录
filename: 'main.js' //输出文件名
}
};
module.exports = config;

在webpack的世界里面,每一个文件都是一个模块,所以不同的文件需要用不同的加载器来处理,如果需要写一些css样式,就需要用到css加载器。

npm install css-loader --save-dev
npm install style-loader --save-dev

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var config = {
//......
module:{
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}

]
}
};

在module的rules属性中可以指定一系列的loaders,每一个loader都必须包含test和use选项,当webpack编译遇到.css结尾的文件,使用该加载器编译。

直到上面这种情况,css是通过JavaScript动态创建style标签来写入的,这样就加重了main.js的代码量,但在实际业务中,可能有多个css样式文件,我们可以把这些文件提取出来,合并成一个main.css文件。

npm install extract-text-webpack-plugin --save-dev

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

var config = {
//......
module:{
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'style-loader',
fallback: 'css-loader'
})
}

]
},
plugins: [
new ExtractTextPlugin("main.css");
]
};
//.....

搭载vue需要使用vue加载器vue-loader、vue-style-loader,还需要使用babel做ES6转换,配置到webpack中可以解析vue文件,需要以下依赖:

npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-es2015
npm install --save-dev babel-runtime

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
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var config = {
//......
module:{
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
css: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'vue-style-loader'
})
}
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'style-loader',
fallback: 'style-loader'
})
}
]
},
plugins: [
new ExtractTextPlugin("main.css")
]
};
//.....
```

babel还需要一个.babelrc的文件,并写入babel配置,webpack会依赖此文件使用babel编译ES6。
```javascript
{
"presets": ["es2015"],
"plugins": ["transform-runtime"],
"comments": false
}

我们可以对webpack进一步配置,来支持更多功能,实现对图片、字体的支持。

npm install --save-dev url-loader
npm install --save-dev file-loader

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
var config = {
//......
module:{
rules: [
//......
{
test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
loader: 'url-loader?limit=1024'
}
]
},
plugins: [
new ExtractTextPlugin("main.css")
]
};
//.....
```

上面是开发环境的基本配置,生产环境打包所以资源都会保存到demo/dist目录下,为方便开发和生产的切换,需添加生产环境的配置文件webpack.prod.config.js,需安装两个依赖:
> npm install --save-dev webpack-merge
> npm install --save-dev html-webpack-plugin

```javascript
// package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --config webpack.config.js",
"build": "webpack --progress --hide-modules --config webpack.prod.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
// webpack.prod.config.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig = require('./webpack.config.js');

//清空基本配置的插件列表
webpackBaseConfig.plugins = [];

module.exports = merge(webpackBaseConfig, {
output: {
publicPath: '/dist/',
filename: '[name].[hash].js'
},
plugins: [
new ExtractTextPlugin({
// 提取css,并从命名为带有20位hash值的唯一文件
filename: '[name].[hash].css',
allChunks: true
}),
//定义当前node环境为生产环境
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
//压缩js
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
}
}),
//提取模板 并保存入口html文件
new HtmlWebpackPlugin({
filename: '../index_prod.html',
template: './index.ejs',
inject: false
})
]
})

通过npm run build运行打包,会在项目目录下生成dist文件,里面就是打包完成的所以静态资源。至此,webpack的一些基本配置已经完成,以下是过程中的一些报错:

1.缺少webpack-cli

缺少webpack-cli

找不到webpack-cli模块,原因是在webpack4.0之后,webpack-cli作为一个工具包独立出来了,npm install -D webpack-cli安装即可。

2.extract-text-webpack-plugin版本太低

版本过低

版本过低,与webpack4.x不兼容,npm install --save-dev extract-text-webpack-plugin@next升级到下一个测试版本,可解决。

3.babel的相关插件版本不统一

版本不统一

babel版本可能是6.x,但是babel-core或者babel-loader的版本达到8.x,解决办法有下面两种:
1.使用webpack 4.x | babel-loader 8.x | babel 7.x,安装npm install -D babel-loader @babel/core @babel/preset-env webpack
2.使用webpack 4.x | babel-loader 7.x | babel 6.x,安装npm install -D babel-loader@7 babel-core babel-preset-env webpack

4.vue-loader新特性

vue-loader新特性

vue-loader在15.x之后的版本都需要使用VueLoaderPlugin,解决办法,先定义一个VueLoaderPlugin变量,再在扩展中使用。
const VueLoaderPlugin = require('vue-loader/lib/plugin');
在webpack.config.js中plugins项添加new VueLoaderPlugin()

5.js压缩旧方法的移除

js压缩错误

在webpack4.x之后移除了UglifyJsPlugin的用法,用config.optimization.minimize代替,解决办法:
npm install --save-dev uglifyjs-webpack-plugin安装该插件
引入并配置该插件:

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

module.exports = {
//...
optimization: {
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: false
}
})
]
}
};

至此,搭载vue的一个自动化工程已经基本配置好了,由于webpack配置内容较为笼统,详细代码请参考:https://github.com/joydezhong/webpack-vue