title: webpack应用
date: 2022-11-29 16:49:56
tags:
基础使用
安装
首先使用npm init初始化项目,然后安装webpack以及webpack-cli
1 | // 全局安装 |
配置文件
在文件根目录下新建webpack.config.js配置文件
1 | const path = require('path') |
打包命令
使用本地环境进行打包输出
1 | npx webpack |
1 | npx webpack --watch // 自动生成 |
核心概念
Entry入口
指示Webpack以哪个文件为入口起点开始打包
Output输出
指示Webpack打包后的资源bundles输出到哪里,以及如何命名
1 | const path = require('path'); |
plugin插件
可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量等。
HtmlWebpackPlugin插件
基本用法
该插件将为你生成一个 HTML5 文件, 在 body 中使用 script
标签引入你所有 webpack 生成的 bundle。 只需添加该插件到你的 webpack 配置中,如下所示:
1 | const HtmlWebpackPlugin = require('html-webpack-plugin'); |
打包后会生成dist/index.html
文件
1 |
|
如果你有多个 webpack 入口,他们都会在已生成 HTML 文件中的 <script>
标签内引入。
如果在 webpack 的输出中有任何 CSS 资源(例如,使用 MiniCssExtractPlugin 提取的 CSS),那么这些资源也会在 HTML 文件 <head>
元素中的 <link>
标签内引入。
devServer
在开发环境中,用于自动编译并自动刷新页面,方便开发过程中的调试。注:该功能只会在内存中编译打包,不会有任何文件输出,如需更新到生产环境中,还需重新打包代码。
安装
1 | npm i webpack-dev-server -D |
配置
在webpack.config.js文件中进行配置
1 | module.exports = { |
启动
1 | npx webpack-dev-server |
loader
webpack只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
warning
webpack的其中一个强大的特性就是能通过import
导入任何类型的模块(例如.css
文件),其中打包程序或任务执行器的可能并不支持。我们认为这种语言扩展时很有必要的,因为这可以使开发人员创建出更准确的依赖关系图
在webpack的配置中,loader有两个属性:
test
属性,识别出哪些文件会被转换use
属性,定义出在进行转换时,应该使用哪个loader
1 | const path = require('path'); |
以上配置中,对一个单独的 module 对象定义了 rules
属性,里面包含两个必须属性:test
和 use
。这告诉 webpack 编译器(compiler) 如下信息:
“嘿,webpack 编译器,当你碰到「在 require()
/import
语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先 use(使用) raw-loader
转换一下。”
chunk、bundle、moudel
module、chunk、bundle 这三个都可以理解为文件,区别在于:我们直接写出来的是 module,webpack 处理时是 chunk,最后生成浏览器可以直接运行的是 bundle。也可以这样理解,module,chunk 和 bundle 其实就是同一份逻辑代码在不同转换场景下的三个名字。
产生Chunk的三种途径
- entry入口
- 异步加载模块
- 代码分割(code spliting)
摘抄自Webpack 理解 Chunk - 掘金 (juejin.cn)
ChunkVSModule
Module
首先来说module,Webpack可以看做是模块打包机,我们编写的任何文件,对于Webpack来说,都是一个个模块。所以Webpack的配置文件,有一个module字段,module下有一个rules字段,rules下有就是处理模块的规则,配置哪类的模块,交由哪类loader来处理。
1 | module: { |
Chunk
Chunk是Webpack打包过程中,一堆module的集合。我们知道Webpack的打包是从一个入口文件开始,也可以说是入口模块,入口模块引用这其他模块,模块再引用模块。Webpack通过引用关系逐个打包模块,这些module就形成了一个Chunk。
资源模块Asset Modules
资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
该方法需将资源在 JS 中通过 import 进行导入或css中进行导入
1 | // js 文件导入 |
资源模块类型
- asset/resource:发送一个单独的文件并导出 URL
- asset/inline:导出一个资源的 Data URI ( 64位图 )
- asset/source:导出资源的源代码
- asset:在导出一个资源的 Data URI 和发送一个单独的文件之间自动进行选择
详情看webpack中文文档[webpack文档](webpack 中文文档 (docschina.org))
resourse,inline,source示例
(解析)[(50条消息) Webpack5资源配置(三)_xiaojian044的博客-CSDN博客_asset/inline]
asset/recource资源:发送一个单独的文件
asset/inline资源:inline这个资源类型用于导出一个资源的data url ,在webpack.config.js中
asset/source资源:导出资源的源代码 ,在webpack.config.js中module.rules中配置:
sset通用资源类型:在导出一个资源的 Data URI 和发送一个单独的文件之间自动进行选择,
webpack按照默认条件,自动的在recource资源和inline资源之间进行选择,小于8kb的文件,将会
视为inline模块类型,否则会被视为resource模块类型,可以通过webpack配置的module rule层级
中,设置rules.parser.dataUrlCondition选项来修改此条件
module.rules中配置:
1 | const path = require('path') |
asset示例
1 | module.exports = { |
index.js
1 | import helloword from "./02.index"; |
Source Map
一种提供源代码到构建后代码映射的技术,如果构建后代码出错了,通过映射关系可以追踪源代码的错误。在 webpack.config.js 文件中配置
1 | module.exports = { |
- source-map:生成外部文件,错误代码的准确信息和源代码的错误位置
- inline-source-map:内联,错误代码的准确信息和源代码的错误位置。在代码底部生成,构建速度比外部文件更快
- hidden-source-map:生成外部文件,错误代码的原因,没有错误位置,无法追踪源代码错误。
- eval-source-map:内联,错误代码的准确信息和源代码的错误位置。每一个文件都生成对应的 source-map
- nosources-source-map:生成外部文件,
- cheap-source-map:生成外部文件,错误代码的准确信息和源代码的错误位置。只精确到行
- cheap-module-source-map:同 cheap-source-map,会将 loader 的 source map 加入
开发环境建议
- eval-source-map
- eval-cheap-module-source-map
生产环境建议
- source-map
- nosources-source-map
- hidden-source-map
资源处理
HTML资源
打包HTML
下载html-webpack-plugin插件
1
2npm i html-webpack-plugin - D
在 webpack.config.js 文件中引入插件并调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 引用插件
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [
// 打包 HTML 文件
new HtmlWebpackPlugin({
// 指定 HTML 模版文件
template: './index.html',
// 指定 Script 标签位置
inject: 'body'
})
]
}- Webpack 会在输出目录中新创建一个 HTML 文件,在原始的 HTML 文件中无需引入 JS 文件,通过 Webpack 编译后的 HTML 文件会自动引入。
样式资源
打包css资源
下载样式处理解析器css-loader与style-loader
1 | npm i css-loader style-loader -D |
在配置文件中添加解析器
1 | module.exports = { |
在 JS 文件中导入 CSS 文件
1 | import '../css/main.scss' |
抽离css代码为独立文件
(正确解析)[(50条消息) webpack5之loader配置(四)_xiaojian044的博客-CSDN博客_webpack5 html-loader]
下载插件mini-css-extract-plugun
1 | npm i mini-css-extract-plugin -D |
引入插件
1 | const MiniCssExtractPligin = require('mini-css-extract-plugin') |
在plugins中引入
1 | plugins: [ |
修改rules的配置对象(删除’style.loader’,修改为[MiniCssExtractPligin.loader
)
1 | { |
CSS 代码压缩(生产模式)
安装插件css-minimizer-webpack-plugin
1 | npm i css-minimizer-webpack-plugin -D |
在配置文件中进行配置
1 | const CssMinimizerPlugin = require("css-minimizer-webpack-plugin") |
- 压缩css代码,仅在生产模式下有效
CSS兼容性处理
下载postcss-loader,postcss,postcss-preset-env模块
1 | npm i postcss-loader postcss postcss-preset-env -D |
在根目录下创建postcss.config.js文件并进行配置
1 | module.exports = { |
引用模块
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') |
postcss-preset-env 帮助 postcss 找到 package.json 中 browserslist 里的配置,通过配置加载指定的 css 兼容性
1 | // 在 package.json 中添加浏览器列表 |
图片资源
下载图片资源处理器
1 | npm i url-loader file-loader html-loader -D |
字体资源
通过CSS引入字体资源
1 | @font-face { |
在 webpack.config.js 文件中进行配置
1 | module.exports = { |
js资源
语法检查
使用 eslint 扫描我们所写的代码是否符合规范,严格意义上来说,eslint 配置跟 webpack 无关,但在工程化开发环境中,他往往是不可或缺的。
安装
1 | npm i eslint -D |
创建配置文件,根据提示选择需要的类型。配置完成后,将在 node_modules 文件夹中生成一个 .eslintrc.json 文件,将文件复制到根目录下。
1 | npx eslint --init |
会出来如下选择
1 | Need to install the following packages: |
JS 兼容处理
将 ES6 代码转换为低版本 ES5 代码
安装模块
- babel-loader: 在 webpack 里应用 babel 解析 ES6 的桥梁
- @babel/core: babel 核心模块
- @babel/preset-env: babel 预设,一组 babel 插件的集合
1 | npm i babel-loader @babel/core @babel/preset-env -D |
在 package.json 中配置
1 | module.exports = { |
regeneratorRuntime
regeneratorRuntime 是 webpack 打包生成的全局辅助函数,由 babel 生成,用于兼容 async/await 的语法
安装
1 | npm i @babel/runtime @babel/plugin-transform-runtime -D |
使用
1 | module.exports = { |
js压缩
安装插件terser-webpack-plugin
1 | npm i terser-webpack-plugin -D |
配置
1 | const TerserWebpackPlugin = require("terser-webpack-plugin") |
代码分离
代码分离是 webpack 中最引人瞩目的特性之一,可将代码分离到不同的文件中,然后将这些文件按需加载或并行加载,同时还可以获取代码加载的优先级。
方法1:入口起点(不推荐)
使用entry配置手动分离代码,如果多个入口共享的文件,会分别在每个包里重复打包
1 | module.exports = { |
方法2:防止重复
使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离代码
1 | module.exports = { |
动态导入
async-module.js
1 | function getComponent() { |
两个重要的应用:懒加载 预加载
懒加载
指的是 JS 文件的懒加载,当事件触发或条件满足后才进行加载。是很好的优化网页或应用的方法。这种方法实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用一些新的代码块。这样加快了应用的初始加载速度,减轻总体体积,因为某些代码块可能永远不会被加载。
1 | document.querySelector('button').addEventListener('click', () => { |
** 这两个斜杠为魔法注释(/ *webpackChunkName: ‘filename’ */) **
预加载
等其他资源加载完毕后再进行加载,当事件触发或条件满足后,才会执行。兼容性较差,只能在pc端高版本浏览器中使用,手机端浏览器兼容较差。
1 | document.querySelector('button').addEventListener('click', () => { |
sliptChunks 插件
1 | module.exports = { |
缓存(生产模式)
使用hash值为文件命名
1 | module.exports = { |
缓存第三方库
将第三方库(library)(例如loadash)提取到单独的vendor.chunk文件中,是比较推荐的做法,这是因为它们很少像本地源代码那样频繁的修改,因此通过实现以上步骤,利用client的长效缓存机制,命中缓存来消除请求,并减少向server获取资源,同时还能保证client代码和server代码版本一致
1 | module.exports = { |
优化
公共路径publicPath
publicPath 配置公共路径,所有文件的引用将自动添加公共路径的绝对地址。
1 | module.exports = { |
环境变量 Environment variable
环境变量可以消除 webpack.config.js 在开发环境和生产环境之间的差异
1 | module.exports = ( env ) => { |
打包命令时如果使用生产模式,则在命令后增加:
1 | npx webpack --env production |
使用TerserPlugin压缩js文件
安装
1 | npm i terser-webpack-plugin -D |
引入
1 | const TerserPlugin = require('terser-webpack-plugin') |
配置
1 | // 压缩css代码块 |
拆分配置文件
目前,生产环境和开发环境使用的是一个配置文件,我们需要将这两个文件单独放到不同的配置文件中。如:webpack.config.dev.js
(开发配置环境),webpack.config.prod.js
(生产配置环境)/在项目根目录下创建一个配置文件夹config
来存放他们
启动
1 | npx webpack -c ./config/webpack.config.prod.js |
webpack.config.dev.js
1 | const path = require('path') |
webpack.config.prod.js
1 | const path = require('path') |
使用merge进行拆分
安装merge
1 | npm install webpack-merge -D |
将公共的内容放到webpack.config.common.js
1 | const path = require('path') |
development.config
1 |
|
producton.config
1 |
|
合并的merge.config
1 | const { merge } = require('webpack-merge') |
devServer使用
配置代理
详细看vue
historyApiFallback
-如果我们的应用是个SPA(单页面应用),当路由到/some时(可以直接在地址栏里输入),会发现此时刷新页面后,控制台会报错
1 | GET http://localhost:300/some 404(Not Found) |
此时打开network刷新并查看,就发现了问题所在—浏览器把这个路由当作了静态资源地址去请求,然而我们并没有打包出/some这样的资源,所以这个歌访问无疑是404,如何解决他,这种时候,我们可以通过配置项来提供页面代替任何404的静态资源响应:
1 | module.exports={ |
此时重启服务器刷新后变成了index.html。当然,在多数业务场景下,我们需要根据不同的访问路径定制替代页面,这种情况下,我们可以使用rewrites这个配置项。类似这样:
1 | module.exports={ |
开发服务器主机
如果你在开发环境中起了一个devServer服务,并期望你的同事访问到它,你只需要配置:
```js
module.exports={
// ..
devServer:{
host:’0.0.0.0’
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-
## '@'来便捷解析路径
```js
const path = require('path')
module.exports={
mode:'development',
entry:'./src/app.js',
resolve:{
alias:{
'@':path.resolve(_dirame,'./src')
}
}
}
在其他需要引用路径时可以使用@替代
依赖图
安装工具
1 | npm i webpack bundle analyzer |
引入插件
1 | const {BundleAnalyzerPlugin}=require('webpack-bundle-analyzer') |
Vue-cli与Webpack之间的联系
vue-cli 里面包含了webpack, 并且配置好了基本的webpack打包规则,