前言

webpack已经很久了,今天就来学学吧。😜。

(第一版其实是2月份的文章了,但是最近这个月决定重新学webpack,所以决定把日期改成最近的时间)

概念

Webpack是一个前端资源加载/打包工具,也是前端工程化的体现。

Webpack基础配置

mode

mode用来告知webpack需要采用对应模式的内置优化。可以在webpack.config.js里设置,也可以在npm命令里添加 --mode参数来设置。有以下两种:

  • development
    1
    2
    3
    4
    5
    6
    7
    8
    // webpack.development.config.js
    module.exports = {
    mode: 'development'
    plugins: [
    new webpack.NamedModulesPlugin(),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
    ]
    }
  • production
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    // webpack.production.config.js
    module.exports = {
    mode: 'production',
    plugins: [
    new UglifyJsPlugin(/* ... */),
    new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.NoEmitOnErrorsPlugin()
    ]
    }

设置mode时同时会把 process.env.NODE_ENV设置为当前环境的值

entry

entry其实就是指定webpack读取项目的起始点,配置方式有以下这些:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const config = {
// 单入口
entry: './entry1',
//多入口
entry: [
'./entry1',
'./entry2'
],
// 多入口时
entry:{
a: './entry1',
//若b有多个入口
b: ['./entry2-a', './entry2-b',],
}
}

loader

首先,webpack本身的打包只是对js文件的打包,那么非js文件怎么打包进来呢?这个时候loader的作用就体现出来了。loader就是一个转译器,它可以把非js文件进行处理,然后使得非js文件可以进入构建包内。

想了解更多的loader信息可点击此处

那么如何使用loader呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const config = {
modules:{
rules:[
{
test: /\.css$/,
// 1. loader不需要做其它配置时
use: 'css-loader',
// 2. loader需要传入参数配置
use: [
loader: 'css-loader',
options:{
modules: true
}
]

}


]
}
}

其实还可以在cli命令里加入以下--module bind 'css=style-loader!css-loader'以及在源码中直接导入 loader的东西,但是这两种方式都不太好,容易导致意外的错误且不易调试。

所以还是推荐写在modules.rules

这里就简单列举一些常用的loader

  • css-loader: 解析css文件
  • style-loader: 把解析好的cssstyle标签显示出来
  • babel-loader: 把es6及之后的语法解析成es5语法,最大的作用就是兼容浏览器。
  • url-loader,file-loader: webpack加载图片, url-loader更像是file-loader的增强版。当设置limit时,超出此范围则用file-loader解析,小于则返回base64格式。
  • raw-loader: 读取文件内的内容,并作为字符串返回
  • sass-loader,less-loader: css预编译文件解析。
  • vue-loader: 解析.vue文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const config = {
modules:{
rules:[
{
test: /\.scss$/,
use:['style-loader', 'css-loader', 'scss-loader']

}
]
}
}
// 调用多个loader时是有顺序的,顺序是从右到左。但实际调用过程上如下所示
// pitch方法意为跳过
|- a-loader `pitch`
|- b-loader `pitch`
|- c-loader `pitch`
|- requested module is picked up as a dependency
|- c-loader normal execution
|- b-loader normal execution
|- a-loader normal execution

plugins

首先,plugin的机制来说我个人觉得和浏览器内的交互事件其实比较类似。因为webpack在运行周期时同样会有很多的事件,所以plugins的作用可以类比于我们在浏览器中对元素的事件监听处理。其实就是我们调用webpack的底层api来编写具体功能的实现。它可以是一个构建时的处理,也可以是对输出结果的优化(其实就是打包优化),还可以对引入资源进行管理。从这里来看,plugins的功能范围对比起loader来说是更加广泛的。

想了解更多的plugins信息可点击此处

那么如何使用plugins呢? 其实只需要在webpack.config.js里的plugins参数里设置就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
plugins:[
// 引入插件然后在这里传入插件的实例化对象,
// new plugin({//插件参数...})

// 举个具体的栗子:
new HtmlWebpackPlugin({
template: './index.html',

})
]
}

以下列举一些常用的插件:

  • mini-css-extract-plugin & extract-text-webpack-plugin
    • 作用:抽离css到单独的文件中并以link引入到html中使用。
    • 使用:webpack >= 4.0 ? mini-css-extract-plugin : extract-text-webpack-plugin
  • html-webpack-plugin
    1
    2
    3
    4
    5
    6
    plugins:[
    new HtmlWebpackPlugin({
    template: './index.html', // 模板html,
    filename: 'index.html', // 目标html
    })
    ]
  • mini-css-extract-plugin
    • 打包的时候提取css到单独的文件,并且支持按需加载和sourceMap
  • progress-bar-webpack-plugin
    • vue-cli 3打包的时候无法显示出打包所花费的时间,加这个可以显示出来
  • purge-css-webpack-plugin
    • 删除未使用的css
  • DLLPlugin和DLLReferencePlugin
    • DLLPlugin主要作用是把一些不经常变化的第三方库单独打包出来,然后会生成一个manifest.json,然后通过DLLReferencePlugin去引用。可以提升构建速度
  • add-asset-html-webpack-plugin
    • 页面打包后,插入我们特定script的引用,来达到全局变量的效果(暴露在Window下)
  • commons-chunk-plugin&split-chunk-plugin
    • 两者主要是用来提取第三方库和公共模块代码,避免首屏加载的bundle文件或者按需加载的bundle文件体积过大,从而导致加载时间过长。
    • 后者是前者的升级版,解决了前者在提取公共代码的重复问题。且webpack4中已经删除了commons-chunk-plugin改用了split-chunk-plugin
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // commons和split的对比

    // commons-chunk-plugin
    chunk-a: react, react-dom, a-comp
    chunk-b: react, react-dom, b-comp
    // 会出现重复代码

    // split-chunk-plugin
    chunk-a ~ chunk-b : react, react-dom,
    chunk-a: a-comp
    chunk-b: b-comp
    // 不会出现重复代码

resolve

resolve的作用是设置模块怎么被解析,数据结构是Object。接下来列举一些比较常用的属性。

alias

alias作用是设置别名,可以使得引入模块变得更加简单。举个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
// 配置
const config = {
resolve:{
alias:{
// path.resolve来确定引入路径不会出问题
"@": path.resolve(__dirname, './src');
}
}
}

// 引入模块时
import HomeView from '@/views/home/index.vue';

extensions

extensions作用是自动扩展,可以自动解析确定的扩展。举个栗子:

1
2
3
4
5
6
7
8
9
10
// 配置
const config = {
resolve:{
// 默认选项是.js .json
extensions: ['.js', 'json', '.vue'],
}
}

// 引入模块时可以不指定扩展(也就是文件后缀名)
import HomeView from '@/views/home/index';

modules

modules作用是告诉webpack解析时应该搜索的目录。举个栗子:

1
2
3
4
5
6
7
8
9
// 配置
const config = {
resolve:{
// 意思是webpack搜索目录优先找src目录下的,没有再从node_modules找
modules: [path.resolve(__dirname, './src/'), 'node_modules']
}
}
// 此时也可以不写前面的 '@/',和alias有异曲同工之妙
import HomeView from 'views/home/index.vue';

devServer

devServer是开发中用来启动本地服务,方便开发。下面举个栗子来说明各属性作用😂

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
// 配置
const config = {
devServer: {
open: false, // 是否自动打开浏览器
port: 8080, // 本地服务启用端口
// webpack中有一个hotModuleReplacementPlugin, hot选项其实就可以当作是否启用了这个插件。
hot: true, // 是否启用热更新
compress: true, // 是否启用gzip压缩
https: true, // 是否启用https
// 是否开启代理
proxy: {
'/api': {
target: 'localhost:3000/', // 对应自己的后端接口
changeOrigin: true, // 请求头中显示target
ws: true, // 是否代理websocket
pathRewrite: {
'^/api': ''
}
}
},
// 是否指定静态文件目录,
contentBase: path.join(__dirname, "public"),
publicPath: '/'
}
}

externals

按照webpack官网里的解释,如果我们想引用一个库,但是又不想把webpack把它打进包里且我们希望可以正常引用这个库。这个时候就可以使用externals配置。例如官网中的栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// index.html
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous">
</script>

//webpack.config.js
const config = {
externals: {
jquery: jQuery
}
}

// 引用
import $ from 'jquery';

$('.my-element').animate(...);

相关文章

【Webpack】项目优化

总结

其实看了这些配置,基础的webpack配置已经没有啥大问题了。还有一些比较小的点就没写了,之后有疑问也可以去webpack中文网查看对应部分配置。