快速开始
定义
基于node.js来开发的静态资源打包工具,最基本的功能是递归解析依赖的文件并打包,顺便把模块化代码转化成可以直接在浏览器上运行的代码。
下载
1 | npm i webpack webpack-cli -D //下载webpack和调用webpack的命令 |
不下载到全局的原因:
不同项目可能需要使用不同版本的webpack
下载到全局无法被项目中的
package.json
文件记录,分享项目给其他人使用的时候需要额外下载webpack,对于没有前端基础的人可能甚至不知道需要下载webpack。
webpack打包命令
如果全局安装:
1
webpack
如果安装到本地
1
npx webpack #npx会自动在node_modules/.bins目录下查找可执行文件,效果和运行package.json中的脚本一样
或者
1
npx webpack --watch #实时监测文件的变化,变化后保存文件自动打包
webpack.config.js
webpack配置文件,在此自定义webpack配置,就不用每次都在命令行中指定配置参数。
这个文件的执行环境是node.js,必须使用cjs语法,使用module.exports
导出配置对象。
常见属性
entry
指定一个入口文件:
1
entry:'./src/main.js'
指定多个入口文件:
1
2
3
4
5
6entry:{
app:'./src/main.js',
app2:'./src/main2.js'
}
//或者
//entry: ['./src/index.js', './src/another-entry.js']更详细的配置:
1
2
3
4
5
6
7entry:{
app:{
import:'./src/main.js',//指定入口文件
dependOn:'lodash',//指定依赖的模块
filename:'page/[name].bundle.js',//指定打包后的js文件名称
} //app是模块名,用来替代[name]的位置
}
output
属性值为一个对象
1 | { |
- filename:打包后输出的js文件名
- path:打包后**所有文件(包括js文件,css文件和图片文件)**的存放位置,必须是
绝对路径
,所以使用path.resolve()
来拼接路径,如果最终拼接的不是绝对路径,还会和当前工作目录拼接
,确保结果是一个绝对路径。 - clean:值为布尔值,为true表示每次打包清除之前的打包文件
- publicPath:指定所有文件的公共路径
mode
定义打包模式(必填)
1 | mode:developmemt||production |
开发模式和打包模式的区别
开发环境:
- 不需要使用文件缓存,所以不需要给文件名额外添加[contenthash]
- 保留devServer
- 删除压缩css,js文件配置
生产环境:
- 需要使用缓存,保留文件额外名[contenthash]
- 删除devServer
- 保留压缩css,js文件配置
- 使用tree-shaking
contenthash
在 Vue 项目中,特别是在使用 Vue CLI 构建项目时,可以通过配置生成带有哈希值的文件名来优化缓存。哈希值通常用于静态资源(如 JavaScript、CSS 和图片)的文件名中,以确保当文件内容发生变化时,浏览器能够识别并下载最新版本的资源,而不是使用旧的缓存。
Vue CLI 基于 Webpack 实现了这一功能,因此可以利用 Webpack 的相关配置,来控制哈希值的生成方式。以下是几种常见的哈希计算方式:
**[hash]**:基于某次构建过程中的编译结果,生成唯一一个哈希值,一次打包后的所有文件共用同一个hash值。这意味着如果构建过程中有任何文件发生了变化,所有输出文件的哈希值都会改变。
1 | output: { |
这会导致每次构建时,所有文件都具有相同的哈希值,即使只有其中一个文件被修改。
[chunkhash]:根据每个入口文件的内容生成哈希值,不同的入口点可能会有不同的 chunkhash
,和这个入口文件有关的文件,它们的chunkhash
值是一样的。这对于多页应用特别有用。
1 | output: { |
当某个入口点下的文件发生更改时,仅该入口点相关的文件哈希值会更新,其他入口点的文件哈希值保持不变。
**[contenthash]**:这是 Vue CLI 推荐的方式,它根据文件内容生成哈希值。对于 CSS 文件,Vue CLI 使用 extract-text-webpack-plugin
或 mini-css-extract-plugin
插件提取样式到单独的文件,并为这些文件生成基于内容的哈希值。
1 | output: { |
这种方法更加精细,只会在文件的实际内容发生变化时才更新其哈希值,从而最大限度地利用浏览器缓存。
devServer
webpack-dev-server
配置的地方
webpack-dev-server是一个由webpack团队维护的,webpack高度支持的独立的工具,用于在开发过程中提供一个开发服务器, 使用不需要导入,但是需要额外下载。
安装:
1 | npm i webpack-dev-server -D |
配置:
1 | module.exports = { |
static属性
提供开发环境中的一个静态资源(比如图片,字体,视频)目录,这意味着你可以通过浏览器访问这些目录下的文件。
在vue和react中,这个静态资源目录都是public目录,public目录下的文件在构建过程中,会被直接复制到输出目录。
proxy
开启代理,关于proxy的介绍,参考《前端面试-vue》一文中跨域的解决办法。
开启服务器
1 | npx webpack-dev-server |
运行这个命令不仅会启动Webpack的打包过程(打包到内存,不输出实际文件),还会启动一个开发服务器,部署的是打包到内存中的文件。这个服务器会监听源文件(src目录下的js文件)的变化,源文件修改并保存会自动重新编译和刷新浏览器。
模块
资源模块
用来加载图片或者字体
asset/resource
返回导出资源打包后的路径,打包后的文件中会包含源文件
1 | module:{ |
用[contenthash]
代替文件名,这意味着会根据文件的内容来确定文件名,如果文件内容改变,这个值也会改变
用[ext]
来代替后缀,表示源文件是什么类型的后缀,打包后的文件也是什么类型的后缀。
图片可以通过import
或者src
的方式被引入
1 | //通常会得到该图片的一个路径或 Base64 编码字符串(取决于你的构建配置) |
asset/inline
返回源文件的data:url
,也就是base64格式字符串,打包后的结果就不会包括源文件了
1 | //通常会得到该图片的一个路径或 Base64 编码字符串(取决于你的构建配置) |
设你有一张 PNG 格式的图片,通过 data URL
和 Base64 编码的方式内联到 HTML 文件中,它可能看起来像这样:
1 | <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." alt="Embedded Image"> |
data:image/png
表示数据的MIME类型,base64
表示数据是否经过了 Base64 编码,如果数据未进行 Base64 编码,则应省略此部分。
这里的 "iVBORw0KGgoAAAANSUhEUgAAAAUA..."
就是该图片经过 Base64 编码后的字符串
asset/source
导出资源的源码,这种方式非常适合需要将小文件的内容,直接包含到代码中的场景,比如模板、小型脚本或样式表等。
1 | module.exports = { |
假设有一个名为 example.txt
的文本文件,其内容为 "Hello, Webpack!"
,你可以通过以下方式将其导入到 JavaScript 文件中:
1 | import content from './example.txt'; |
在这种情况下,content
变量将会包含 example.txt
文件的所有文本内容。
注意事项
- 仅限文本文件:
asset/source
最适合用于文本文件。如果你尝试用它来处理二进制文件(如图片、字体),可能会导致不可预料的结果,因为这些文件的二进制数据会被当作字符串处理。 - 文件大小:虽然可以将任何大小的文件作为源代码导入,但通常建议只对较小的文件这样做,以避免增加最终打包文件的体积。
asset
webpack将按照默认条件,自动地在resource
和 inline
之间进行选择,小于8kb
的文件,将会视为inline
模块类型,否则会被视为resource模块类型。也可以修改这个配置文件。
1 | module:{ |
loader
扩展webpack的功能,帮助webpack解析其他类型(非js类型)的文件,并把这些文件转换成有效的模块,实现代码转换;只要有对应的loader,万物皆是模块。
loader在webpack.config.js文件中使用的时候通常不需要导入,直接使用即可, Webpack 会根据配置中的名称自动查找并使用相应的加载器,而对于插件,需要导入然后手动创建实例。
解析css文件
我们需要下载css-loader,以及style-loader或者mini-css-extract-plugin
style-loader: 把解析后的css样式放到打包后的html文件的style标签中
mini-css-extract-plugin:把css提取为单独的文件,多个css文件会合并为一个单独的css文件,在html-webpack-plugin插件的作用下还会自动在html文件中引入(在head标签中),关于这两个插件的作用在后文有介绍
1 | module:{ |
loader是支持链式调用的,顺序从右往左,就拿上面的例子来说,先对css文件使用css-loader,再使用style-loader。
注意:单纯打包css文件不会修改原来的css代码,也不会压缩代码,只是把原来的css代码放到一个文件中。压缩,修改css代码需要借助其他插件。也就是说,单纯借助上述的3个工具,只能做到提取css代码,无法对css代码进行优化。
babel-loader
webpack本身只能对js代码打包,压缩,不能进行ES6到ES5的转换,需要借助babel-loader将新的语法转换成低版本的语法,实现语法降级,提高代码的兼容性,比如对esm语法的转化。
安装:
1 | npm i babel-loader @babel/core @babel/preset-env --save-dev |
babel-loader
是一个 Webpack 加载器,用于在 Webpack 构建过程中使用 Babel 转译 JavaScript 代码。
@babel/core
是 Babel 的核心库,负责执行实际的代码转译工作
@babel/preset-env
是一个智能预设,可以根据目标环境自动选择需要的 Babel 插件,以生成兼容的代码。
配置:
1 | module: { |
代码分离
我们可能在不同的文件引入相同的模块,这样就可能出现重复打包的问题。
将公共的代码抽离出去,减小啊打包后文件的大小,从而提高首屏的加载效率。
模块抽离
在得知哪个模块被重复引用的前提下,抽离出该模块。
1 | entry:{ |
动态导入
1 | import('./math.js')//返回一个promise对象 |
如果引入的模块是命名导出,传入then方法的回调函数的参数格式形如
1 | { |
调用then时可以使用解构赋值来模仿按需导入
1 | export const add = (x,y)=>{ |
如果是默认导出,传入回调函数的参数格式形如下:
1 | { |
动态导入的文件打包的时候会被自动抽离为一个单独的模块,最终输出为一个单独的文件,使用的时候再被导入,即便没有被多次使用,因为是动态导入的,所以不参与模块的静态依赖分析。
魔法注释
1 | import(/* webpackChunkName:'math' */'./lazy.js') //指定动态导入的文件打包后的模块名(也许不是最后文件名) |
split-chunks-plugin
使用插件split-chunks-plugin,后文有关于这个插件的介绍
插件
html-webpack-plugin
生成一个自动引用打包后的文件的html文件,包括mini-css-extract-plugin
生成的css文件,会自动注入打包后的html文件中。
安装:
1 | npm i html-webpack-plugin -D |
在webpack.config.js中配置:
1 | const HtmlWebpackPlugin = require(' html-webpack-plugin') //引入 |
构建多页面应用:在plugins里new多次HtmlWebpackPlugin
自定义打包后的html的标题:
- 在配置对象中添加titile属性并赋值
- 在html模板中的title标签内容替换为
<%= htmlWebpackPlugin.options.title %>
mini-css-extract-plugin
把导入的css文件的所有css代码,提取到一个单独的css文件里,代替style-loader
安装:
1 | npm i mini-css-extract-plugin -D |
配置:
1 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') |
css-minimizer-webpack-plugin
压缩打包后的css文件
安装:
1 | npm i css-minimizer-webpack-plugin -D |
配置:
1 | const CssMinimizeWebpackPlugin = require('css-minimizer-webpack-plugin') |
split-chunks-plugin
自动抽离重复引用的模块,无需下载,webpack内置,,但自动抽离代码在大型项目中使用时,构建过程较费时
配置:
1 | module.exports = { |
webpack-bundle-analyzer
可以帮助开发者可视化和分析 Webpack 打包后的文件大小和内容,它生成一个交互式的报告,显示每个模块的大小及其在最终打包文件中的占比,从而帮助识别和优化代码。
安装:
1 | npm i webpack-bundle-analyzer -D |
配置:
1 | const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer') |
terse-webpack-plugin
用来压缩js代码,但是Webpack 5 内置了对 Terser 的支持,在生产模式下会自动使用 Terser 进行js代码压缩,这一功能已经是webpack核心功能的一部分。但是如果需要自定义 Terser 的选项,仍然需要安装 terser-webpack-plugin
并进行相应的配置。这时,terser-webpack-plugin
是作为一个第三方插件来使用的。
tree-shaking
在前端面试—webpack | 三叶的博客中已介绍,不赘述。
搭建vue脚手架
npm包下载
webpack开发必备:
1 | npm i webpack webpack-cli html-webpack-plugin webpack-dev-server -D |
vue相关:
1 | npm i vue-template-compiler vue-loader -D |
vue-template-compiler
用来解析vue模板
vue-loader
用来解析.vue文件
配置vue-loader:
1 | const {VueLoaderPlugin} = require('vue-loader') //vue-loader还包含一个plugin |
css相关:
1 | npm i css-loader mini-css-extract-plugin -D |
sass相关:
1 | npm i sass sass-loader -D |
babel相关:
1 | npm i babel-loader @babel/core @babel/preset-env -D |
生产环境相关:
1 | npm i vue axios vue-router |
注意vue下载的是vue2
模拟vue-cli打包
1 | { |
完整配置文件
1 | const path = require('path') |