一、webpack基础介绍
1. webpack是什么?
本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。
2. 为什么用webpack
原生浏览器,不能很好的识别 ES6 以及更高版本中ES moudule模块引入方式。代码中使用ES moudule ,可以通过webpack进行打包编译成浏览器识别的语法。
3、webpack安装使用的三种方式
- global全局安装
// 全局安装
npm install webpack -g
// 全局下打包
webpack index.js
- local项目安装
// 本地项目安装
npm install webpack --save-dev
// 本地项目打包
npx webapck index.js //直接执行 npx webpack 会调用默认配置文件 webpck.config.js
- scripts配置安装
// scripts标签使用
"scripts": {
"build": "webpack"
},
// 本地项目打包
npm run build
4、webpack打包信息分析
二、loader
webpack处理js文件以外的文件时,就需要借助loader了
webpack 可以使用 loader 来预处理文件。这允许你打包除 JavaScript 之外的任何静态资源。
1、file-loader
将文件发送到输出文件夹,并返回(相对)URL。 可打包:图片、text等各种文件
2、url-loader
像 file loader 一样工作,但如果文件小于限制,可以返回 data URL
如果小于limit值,直接以base64形式打包到js中,大于和file-loader一样,生成文件。配合使用,优化。
3、style-loader
将模块的导出作为样式添加到 DOM 中
4、css-loader
解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码
// importLoaders 用于配置「css-loader 作用于 @import 的资源之前」有多少个 loader。
模块化打包css文件
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2, // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
},
},
'postcss-loader',
'sass-loader',
],
// modules 选项启用/禁用css模块规范和设置基本行为。
options: {
modules: true,
},
5、postcss-loader
使用 PostCSS 加载和转译 CSS/SSS 文件
三、plugins
webpack 有着丰富的插件接口(rich plugin interface)。webpack 自身的多数功能都使用这个插件接口。这个插件接口使 webpack 变得极其灵活。
1、clean-webpack-plugin
A webpack plugin to remove/clean your build folder(s).
2、HtmlWebpackPlugin
简单创建 HTML 文件,用于服务器访问
3、SplitChunksPlugin
此配置对象表示splitchunksplugin的默认行为。
// webpack.config.js
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async', // 包括:all、async、initial(同步)
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
automaticNameMaxLength: 30,
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};
4. MiniCssExtractPlugin
这个插件将css提取到单独的文件中。它为每个包含css的js文件创建一个css文件。它支持按需加载css和sourcemap。
它建立在新的webpack v4特性(模块类型)之上,需要webpack 4才能工作。
与extract-text-webpack-plugin相比:
- Async loading
- No duplicate compilation (performance)
- Easier to use
- Specific to CSS
TODO:
- HMR support
四、开发环境下配置
1、devtool
此选项控制是否生成,以及如何生成 source map。
// 最佳实践:
development: cheap-module-eval-source-map
production: cheap-module-eval-source-map
2、webpack-dev-server
webpack-dev-server 为你提供了一个简单的 web server,并且具有 live reloading(实时重新加载) 功能。
注意
:new HtmlWebpackPlugin( { // Also generate a test.html filename: 'index.html', // 使用webapck-dev-server打包至内存,需要index.html template: './index.html' } ),
3、HMR
模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新所有类型的模块,而无需完全刷新。
4、babel处理es6
- 补充基础语法
桥梁:
babel-loader @babel/core处理:@babel/preset-env
五、优化
1、tree shaking
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export。这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。
2、Code Splitting
代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
常用的代码分离方法有三种
- 入口起点:使用
entry配置手动地分离代码。 - 防止重复:使用
SplitChunksPlugin去重和分离chunk。 - 动态导入:通过模块中的内联函数调用来分离代码。
Code splitting这个概念一直都有,并非webpack独创,只是现在webpack将此功能集成了。 注意: webapck在做代码分割时,打包同步和异步引入的代码是有区别的。
- 打包同步代码时,只有在配置文件中做配置,
webpack才会将类似lodash的库文件和业务代码做分割打包,否则会打包到一个文件中。
// 同步引入
import _ from 'lodash'
_.join(['a', 'b'], '?')
// webpack.config.js
optimization: {
splitChunks: {
chunks: "all"
}
},
- 打包异步引入的代码时,即使配置文件中没以设置,
webpack也会默认将库文件和业务代码分开打包。
// 异步引入
function getComponent() {
return import('lodash').then(({default: _}) => {
var element = document.createElement('div')
element.innerHTML = _.join(['a', 'b'], '?$')
return element
})
}
getComponent().then(element => {
document.body.appendChild(element)
})
Prefetching/Preloading
webpack v4.6.0+ 添加了预取和预加载的支持。
在声明 import 时,使用下面这些内置指令,可以让 webpack 输出 "resource hint(资源提示)",来告知浏览器:
- prefetch(预取):将来某些导航下可能需要的资源
- preload(预加载):当前导航下可能需要资源
与 prefetch 指令相比,preload 指令有许多不同之处:
- preload chunk 会在父 chunk 加载时,以并行方式开始加载。
- prefetch chunk 会在父 chunk 加载结束后开始加载。
- preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
- preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk会用于未来的某个时刻。浏览器支持程度不同。
3、懒加载
懒加载或者按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把你的代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。
4、Caching?既然contenthash变了,为什么浏览器访问,还是不是最新的?
Output Filenames
我们可以通过替换output.filename 中的 substitutions 设置,来定义输出文件的名称。webpack 提供了一种使用称为 substitution(可替换模板字符串) 的方式,通过带括号字符串来模板化文件名。其中,[contenthash] substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时,[contenthash] 也会发生变化。
5、Shimming
webpack compiler 能够识别遵循 ES2015 模块语法、CommonJS 或 AMD 规范编写的模块。然而,一些 third party(第三方库) 可能会引用一些全局依赖(例如 jQuery 中的 $)。因此这些 library 也可能会创建一些需要导出的全局变量。这些 "broken modules(不符合规范的模块)" 就是 shim(预置依赖) 发挥作用的地方。
6、Environment Variables
想要消除 开发环境 和 生产环境 之间的 webpack.config.js 差异,你可能需要环境变量(environment variable)。
webpack 命令行 环境配置 的 --env 参数,可以允许你传入任意数量的环境变量。而在 webpack.config.js 中可以访问到这些环境变量。例如--env.production 或 --env.NODE_ENV=local(NODE_ENV 通常约定用于定义环境类型,查看这里)。
webpack --env.NODE_ENV=local --env.production --progress