Webpack 属于在项目中配置一次就很少改动的那种工具,但这样就导致新项目再配置 Webpack 时会有些生疏,所以将 Webpack 核心概念及常用配置记录如下。

1)核心概念

Webpack 4.x 之前的核心概念有四个:entry,output,loaders,plugins,4.x 之后增加了 mode。含义如下:

  • Entry:指定 webpack 从哪个 file 开始构建他的依赖关系图,可以有一个和多个,推荐对象表示法;
  • Output:webpack 构建完成后的 bundles 输出位置及 name,其中 name 一般根据 entry 的 file name 动态生成;
  • Loaders:webpack 可以将非 js 文件(css、图像等)通过 loaders 处理成可供我们的应用使用的 modules。也因此在配置文件中,loaders 写在module对象下面,因为 loaders 处理后返回的是有效 modules。
  • Plugins:如果需要额外的功能,比如压缩代码、提取 css、分析打包性能,可使用插件完成;

    Loaders 将特定文件转换为有效 module,而 plugin 扩展性更强

  • Mode:接受developmentproductionnone三个值,一般指定为前两个值的一种,webpack 内部针对不同环境做优化。

2)配置

下面介绍的配置都是module.exports的直接属性,比如:

module.exports = {
entry: {},
output: {},
// loaders 配置位置有些特殊,不知直接写 loaders 对象,而是将它鞋子啊 module 对象下面
// 因为 loaders 处理完后返回的是有效 modules
// 不是 复数!!!
module: {},
// plugin 是数组
// 是 复数!!!
plugins: []
};

同时,文件头引入相应依赖的过程省略了,实际开发中请自行引入。

2.1 Entry

Entry 指定哪些文件作为 webpack 打包入口,可以有一个或者多个:

entry: {
index: './src/js/view/index.js',
people: './src/js/view/people.js',
login: './src/js/view/login.js',
}

2.2 Output

Output 指明 Webpack 处理完成后的 bundles 输入位置及文件 name:

output: {
// 输入目录,这里使用了 node 的 path 模块
path: path.resolve(__dirname, 'dist'),
// [] 里面的内容表示变量
filename: 'js/[name].[contenthash:8].js',
// 静态资源在 html 引用的公共目录
publicPath: '/',
}

Output 配置相对复杂:

2.2.1 output.path

即输出文件目录,推荐使用绝对路径,其中__dirname在 Node 的 path 模块中表示当前目录(即 webpack.config.js 的目录)的绝对路径,resolve方法可以拼接两个目录;

后一个目录可以加/也可以不加,此处无差别

2.2.2 output.filename

表示输出文件名称,这里注意,[]中是变量,其中name由在 entry 中定义的文件名决定,并且,有多少个输入文件,对应有多少个输出文件,后面的contenthash:8表示 chunk 的 hash 值,后文介绍;

实际输出文件一般多于输入文件,因为提取公共代码、设置 sourcemap 都会单独生成输出文件

2.2.3 output.publickPath

这个配置想最为复杂,它的作用是配合 loaders 或 plugins 中设置的资源路径,指定静态文件(css、js、img)插入 html 中的引用路径,简单讲,就是 对输出的静态资源进行目录管理。这里直接使用 详解 Webpack2 的那些路径的描述,只稍作说明。

静态资源最终引用路径计算公式:

html 静态资源路径 = output.publicPath + loaders/plugins 中设置的资源路径

比如:

// publicPath 设置
output.publicPath = '/static/' // JS output.filename 配置
{
filename: 'js/[name].js'
}
// JS 最终访问路径为
output.publicPath + 'js/[name].js' = '/static/js/[name].js' // 图片资源, file-loader,这里省略了 file-loader 其他配置,只列出指定输出路径及文件名的配置
{
name: 'img/[name].[ext]'
}
// 图片最终的访问路径为
output.publicPath + 'img/[name].[ext]' = '/static/img/[name].[ext]' // CSS,ExtractTextPlugin 为提取 CSS 的插件
new ExtractTextPlugin("css/style.css")
// CSS 最终访问路径为
output.publicPath + 'css/style.css' = '/static/css/style.css'

我们上述指定publicPath为绝对路径,实际上,也支持相对路径,相对于index.html,用的比较少。

publicPath默认为空字符串,但为了使输出目录更加条理,推荐使用publicPath对静态资源进行目录管理。

2.3 Loaders

Loaders 的配置写在module对象中,如前所述,因为 loaders 最终返回的是有效 modules,故使用了module命名,注意是单数。这节介绍 loaders 配置及常用 loaders 两部分内容。

2.3.1 loaders 配置

loaders 规则写在 module.rules 里面(不知道为什么不直接写在 module 中),其中 rules 是个数组,可接受一个或多个 loader 配置。两点需要注意:

1)如果某类型需要多个 loader 进行处理,在 use 中按 从右往左 的顺序流式处理;
2)每个 loader 可以进行额外配置。

module: {
// 含有 rules,这一个属性
// rules 是数组,每个元素对应一个 loader 配置
// loader 配置本身是个对象
rules: [
{
// 正则匹配文件,最终匹配的是一个路径,具体间解析 zepto 源文件时的设置
test: /\.scss$/,
// 使用的 loader,可以字符串(单个 loader)、数组(多个 loader)
// 如果是数组,从右往左开始解析
use: ['style-loader', 'css-loader', 'scss-loader'],
},
{
test: /\.(png|jpg|jpeg|svg|gif)$/,
// 每个 loader 可进行额外配置
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[ext]',
},
},
],
},
],
},

2.3.2 常用 loader

  • babel-loader:es6+语法转换;
  • html-loader:解析 html 文件;
  • css-loader:解析 css 文件;
  • sass-loader:解析 scss/sass 文件;
  • style-loader:将解析后的 css 嵌入 js;
  • file-loader:解析图片文件;
  • url-loader:具有 file-loader 的全部功能,同时可以提取小图片为 base64(如果开启 HTTP2 这样增大 静态资源体积反而不好?);
  • postcss-loader:完成 css 自动化处理,比如添加前缀、压缩 css、自动生成雪碧图等

    postcss 本身支持插件扩展,常用的有 autoprefixer、cssnano、postcss-sprites,更多参考官网介绍
    要在 css-loader 之前处理 css:use: [MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader']

Vue 相关

  • vue-loader:解析 vue 文件;
  • vue-style-loader:解析 vue 中的样式文件。

2.4 Plugins

同 loaders 一样,分配置和常用 plugins 两部分

2.4.1 plugins 配置

Plugins 使用相对简单,配置项写在plugins(复数)数组中,元素为插件的实例(通过new调用),生成实例的时候可接收参数,具体看相应插件文档。见下面代码及注释:

plugins: [
// 带有参数
new CleanWebpackPlugin(['dist']),
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
chunkFileName: '[id].[contenthash:8].css',
}),
// 直接调用
new UglifyJsPlugin(),
],

2.4.2 常用 plugins

  • html-webpack-plugin:将构建后的静态文件动态插入 html 中;
  • webpack-merge:实际项目中,一般将 webpack 配置文件拆分为 base、dev、pro,这个插件用户合并配置文件;
  • webpack.HotModuleReplacementPlugin:热更新插件,webpack 内置;
  • clean-webpack-plugin:清除指定文件夹,一般是构建的目录(大型项目慎用,更新需要时间);
  • mini-css-extract-plugin:提取 css 文件,减小增量更新成本(需要在module代理 style-loader 处理 css);

    style-loader 先把 css 嵌入 js 使其变成有效 module,这个插件将 css 从 js 中分离出来。这个过程不矛盾,因为最开始 webpack 无法处理 css 文件,所以需要 css-loader, style-loader 处理,嵌入到 js 中的 css mini-css-extract-plugin 可以识别并提出。这个插件是 webpack 4.x 新引入,代替 extract-text-webpack-plugin。

  • optimize-css-assets-webpack-plugin:将提取出的 css 做进一步优化;
  • uglifyjs-webpack-plugin:不仅仅是压缩代码,还进行了 tree shaking 工作
  • webpack-bundle-analyzer:打包后文件图形化展示工具,一目了然各文件体积;
  • ProvidePlugin:webpack 内置,提取第三方库的 api,比如通过 $ 符号调用 jq

    如果不是通过 npm 安装,而是直接在项目中引入,需要配合resolve的别名使用,不然找不到

2.5 Mode

接受developmentproductionnone三个值,一般取前两个值之一,指定构建环境,webpack 本身会做相应优化(配合optimization使用,下文会有更多介绍),同时省去在命令行中指定构建环境的过程。

// 相当于 webpack --mode=production
mode: 'production',

2.6 其他

上述配置对应 Webpack 核心概念,除此之外,还有下面配置项很常用。

2.6.1 optimization

这个选项是在 Webpack 4.x 中引入的,最常用的配置是代替CommonsChunkPlugin提取公共代码。下面直介绍提取公共 JS 代码的配置:

optimization: {
splitChunks: {
// 只对入口文件处理
chunks: 'initial',
cacheGroups: {
vendor: {
// split `src/js/vendor` 目录下共用的代码到`vendor.js`
// 这里指的是第三方库,很少改动,故单独做持久化缓存
// 注意,目前 splitChunks 在 split css 时有 bug?现在只 split js 代码
// 不推荐直接匹配 node_modules 文件夹,如上,因为涉及 css,打包后 css 错误
test: /src\/js\/vendor\//,
name: 'vendor',
// 只要第三方库,只要 > 0B, 就 split 出来
minSize: 0,
// 只要被引用一次,也要分离出来
minChunks: 1,
// priority: 10,
// enforce: true,
},
common: {
// split `src/js/common` 目录下共用的代码到`common.js`
// 这里是自定义的公共 js 代码,改的频率比第三方库要高,但比具体页面的 js 文件低
// 故单独 split 出来做持久化缓存
// 不一定共用才 split ,很少改动的也 split 出来,如上的 vender.js
// 但此处至少两个共用 minChunks 才抽出
test: /src\/js\/common\//,
name: 'common',
minChunks: 2,
minSize: 0,
// priority: 9,
// enforce: true,
},
},
},
},

2.6.2 devtool

devtool最常用功能是配置 sourcemap,生产和开发环境一般使用不同的 sourcemap,配置如下:

// 生产环境
devtool: 'source-map', // 开发环境
devtool: 'cheap-module-eval-source-map',

关于各配置项的含义可参考Devtool和这片文章Webpack 的 devtool 和 source maps

sourcemap 是构建后的代码 map 到源代码的映射表,便于定位 bug,具体的映射关系存储在构建后的.map文件中。

NOTE: 这里我们在生产环境使用的是 source-map 选项而不是其他,是因为目前 webpack 在开启 uglifyjs-webpack-plugin 优化代码后,其他模式下的 sourcemap 选项无效,官网对此也有说明。虽然使用source-map选项生成的映射表比较大,但只有开启开发者工具的时候.map文件才会加载,这意味着 映射表文件的大小不影响正常用户的访问体验,但是否压缩 js 文件对正常用户有直接影响,故,现阶段,生产环境 devtool 使用 source-map 选项。

2.6.3 devServer

开发环境为了更好的开发体验,可以开启热更新等功能,在devServer中配置:

devServer: {
open: true,
hot: true,
},

需要在插件中进行下面配置:

plugins: [
new webpack.HotModuleReplacementPlugin(),
],

NOTE:如果传统多页面项目,在入口文件后面添加下面代码,配合热更新:

// 配合 webpack 配置实现热更新
if (module.hot) {
module.hot.accept();
}

多页面目前只有在 JS 或者 CSS 文件改变的时候实现了热更新,如果是模版(html)文件改变,没有实现热更新(可以实现自动刷新页面,但感觉很鸡肋,如果改动了模版文件,手动刷新)。

devServer 还可以设置反向代理,后续填坑。

2.6.4 resolve

resolve 选项可以指定如何解析 modules,更多是通过设置 alias 告诉 webpack 去哪找文件解析。比如,如果在项目中通过文件的形式引入的 jq,那在使用 ProvidePlugin 对 jq 进行解析的时候,就需要通过设置别名的形式告诉 webpack 去哪找 jq 源文件。

resolve: {
alias: {
// 后面加 $ 符号表示精确匹配
jquery$: path.resolve(__dirname, 'path/jquery.min.js');
}
} // 解析插件
new webpack.ProvidePlugin({
// 加载 jquery
$: 'jquery',
}),

3)常见需求详细配置

下面记录针对具体需求的完整代码描述。

3.1 引入第三方库

比如,jq,zepto 等,如果通过 CDN 可以在项目中直接使用 $ 符号,但如果是通过 npm 安装到本地,甚至直接将第三方库源文件写在项目中,那是无法直接使用 $ 符号这种调用方式的,需要使用上文介绍的 ProvidePlugin 插件。当然,还有细节需要注意,见下面详细代码。

3.1.1 使用 npm 引入

相对于直接引入,使用 npm 可以省去我们手动指定 module 路径的麻烦,已 zepto 为例:

使用 zepto 时,直接使用 ProvidePlugin 会报错,具体参考这片文章如何在 webpack 中引入未模块化的库,如 Zepto

// 处理 zepto 模块化问题,需要安装 exports-loader 和 script-loader
{
test: require.resolve('zepto'),
use: ['exports-loader?window.Zepto', 'script-loader'],
}, // 给 zepto 设置别名,可以任何名称
plugins: [
new webpack.ProvidePlugin({
$: 'zepto',
}),
],

3.1.2 直接在项目中引入源文件

同 npm 不同之处在于我们需要手动指定 zepto 的路径,如下

// 设置别名
resolve: {
alias: {
zepto$: path.resolve(__dirname, 'src/js/vendor/zepto.min.js'),
},
}, // 处理 zepto 模块化问题
{
// test 路径也要跟着改变,不知道为什么不能用上面指定的别名。。
test: path.resolve(__dirname, 'src/js/vendor/zepto.min.js'),
use: ['exports-loader?window.Zepto', 'script-loader'],
}, // 给 zepto 设置别名,可以任何名称
plugins: [
new webpack.ProvidePlugin({
$: 'zepto',
}),
],

3.2 提取 css

为了能将 css 从 js 中提取出来,需要在 module 中将 style-loader 替换为 MiniCssExtractPlugin.loader,见下面代码:

module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
},
],
}, plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[contenthash:8].css',
// 这个干嘛用?
chunkFileName: '[id].[contenthash:8].css',
}),
],

3.3 缓存控制

主要一下几个方面:

  • 提取 css,添加 contenthash(使用 mini-css-extract-plugin);
  • 提取公共代码(工具函数等,更改频率相比业务代码要小),添加 contenthash,使用 webpack 自带 splitChunks 提取;
  • 提取第三方库代码(比如 jquery,更改频率相比公共代码还要小),添加 contenthash,使用 webpack 自带 splitChunks 提取;
  • 图片可以直接打 hash(图片文件添加 hash 并不一样,也不会随每次构建改变,还不知原理,反正可以工作,待填坑)。

Webpack 备忘录的更多相关文章

  1. Vuex2.0+Vue2.0构建备忘录应用实践

    一.介绍Vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,适合于构建中大型单页应用. ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. webpack之傻瓜式教程

    接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpack教程满天飞,但是却很难找到一个能让新人快 ...

  4. 细说前端自动化打包工具--webpack

    背景 记得2004年的时候,互联网开发就是做网页,那时也没有前端和后端的区分,有时一个网站就是一些纯静态的html,通过链接组织在一起.用过Dreamweaver的都知道,做网页就像用word编辑文档 ...

  5. Webstorm+Webpack+echarts构建个性化定制的数据可视化图表&&两个echarts详细教程(柱状图,南丁格尔图)

    Webstorm+Webpack+echarts   ECharts 特性介绍 ECharts,一个纯 Javascript 的图表库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(I ...

  6. 使用webstorm+webpack构建简单入门级“HelloWorld”的应用&&引用jquery来实现alert

    使用webstorm+webpack构建简单入门级"HelloWorld"的应用&&构建使用jquery来实现 1.首先你自己把webstorm安装完成. 请参考这 ...

  7. webpack入门教程之Hello webpack(一)

    webpack入门教程系列为官网Tutorials的个人译文,旨在给予想要学习webpack的小伙伴一个另外的途径.如有不当之处,请大家指出. 看完入门教程系列后,你将会学习到如下内容: 1.如何安装 ...

  8. webpack的使用

    1.webpack是什么? 打包前端项目的工具(为项目提高逼格的东西). 2.webpack的基本命令 webpack#最基本的启动webpack命令 webpack-w #提供watch方法,实时进 ...

  9. Webpack 配置摘要

    open-browser-webpack-plugin 自动打开浏览器 html-webpack-plugin 通过 JS 生成 HTML webpack.optimize.UglifyJsPlugi ...

随机推荐

  1. 手机web——自适应网页设计(html/css控制)http://mobile.51cto.com/ahot-409516.htm

    http://mobile.51cto.com/ahot-409516.htm 一. 允许网页宽度自动调整: "自适应网页设计"到底是怎么做到的? 其实并不难. 首先,在网页代码的 ...

  2. fiddler 工具使用配置

    前言: 之前为了手动测试项目组之间提供的接口,确定到底是哪一个接口出了问题.一般情况下,我们都直接采用了 Google 浏览器上,F12 后,Network 找到想要的 URL,然后,直接在浏览器上访 ...

  3. MyBatis批量添加和删除

    一.批量插入 二.批量删除

  4. TensoFlow的tf.reshape()

    tf.reshape(tensor,shape,name=None) 函数的作用是将tensor变换为参数shape形式,其中的shape为一个列表形式,特殊的是列表可以实现逆序的遍历,即list(- ...

  5. eclipse .setting下各文件详解

    Eclipse项目中系统文件介绍 一. 写在前面 文章较长,可以直接到感兴趣的段落,或者直接关键字搜索: 请原谅作者掌握的编程语言少,这里只研究Java相关的项目: 每一个文件仅仅做一个常见内容的简单 ...

  6. 手机程序的app包名查找,可以在手机上查到

    获取pkgname(安卓软件包名) 1. 先下载pkgName安装文件(pkgName.apk )并在手机上安装2. 打开刚刚安装的pkgName软件,软件会自动生成你手机上软件的包名列表,同时会在手 ...

  7. 命令行编译C++程序

        使用命令行来编译C++程序,我们可以有两种方法:     方法一:     1. 依次打开开始程序->Visual Studio 2010 –>Visual Studio tool ...

  8. MySQL死锁分析

    死锁问题背景 做MySQL代码的深入分析也有些年头了,再加上自己10年左右的数据库内核研发经验,自认为对于MySQL/InnoDB的加锁实现了如指掌,正因如此,前段时间,还专门写了一篇洋洋洒洒的文章, ...

  9. 【VirtualBox】共享文件夹失效问题

    fix: sudo ln -f -s /opt/VBoxGuestAdditions-5.1.20/lib/VBoxGuestAdditions/mount.vboxsf /sbin/mount.vb ...

  10. Nginx以服务方式启动并用定时任务每天备份日志

    1.安装Nginx以服务方式启动: a.下载 instsrv.exe.srvany.exe 以管理员方式启动CMD执行以下命令: instsrv Nginx D:\nginx\srvany.exe b ...