安装
webpack基于node环境,所以安装webpack前先安装node
npm install webpack webpack-cli --global
npm i webpack webpack-cli -D
第一种是全局安装,但是官方不建议我们使用全局安装,全局安装的话很可能更新不及时
第二种是在项目中安装
安装后可查看项目webpack版本信息
npx webpack --version
我安装的版本是:后面的内容都是这个版本
"webpack": "^5.72.1",
"webpack-cli": "^4.9.2"
webpack5默认情况下会以 ./src/index.js文件为入口文件开始打包,打包后输出到dist文件夹内,文件名为,main.js
webpack五大核心概念
1>entry入口
以哪个文件为入口起点开始打包,分析构建内部依赖图
2>output输出
打包后的资源输出到哪里,打包后的文件如何命名
3>loader预加载
Webpack自身只能理解js/json文件,loader可以告诉webpack怎么处理非js文件
4>plugins插件
可以执行更广的任务,从打包优化和压缩,一直到重新定义环境中的变量等
5>mode模式
开发模式:development
生产模式:production
这个命令缺点是浏览器不能自动刷新
npx webpack
npx webpack --watch // 监听文件变化,保存时有变化就会自动打包
开发环境为了更加方便,我们借助webpack-dev-server
npx webpack-dev-server
npx webpack-dev-server --open // 自动打开浏览器
npm run serve // 就相当于执行了npx webpack-dev-server
1> npm init -y,初始化项目文件
2> npm i webpack webpack-cli -D 项目安装webpack
3> 新建webpack.config.js文件,设置最基本的打包配置
const path = require("path");
module.exports = {
entry: "./src/firstFile.js",
output: {
filename: "firstWebpack.js",
path: path.resolve(__dirname, "dist"),
},
mode: "none",
};
4> npx webpack打包
打包结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDTFzMp7-1653203689296)(C:\Users\lucas\Desktop\学习\图片\firstWebpack.jpg)]
我们在index.html文件中引入打包后的js文件,浏览器打开,控制台输出this is my first webpack
这样,我们就完成使用webpack打包一个js文件
因为我们的webpack只支持js的打包处理,所以其他类型的文件资源就需要借助loader来处理了
安装插件
npm i html-webpack-plugin -D
webpack.config.js中引入插件并进行相关配置
const HtmlWebpackPlugin = require("html-webpack-plugin");
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html", // 模板是哪个html文件
filename: "index.html", // 打包后生成的html文件名称
inject: "body", // js文件的位置,这里放入了body标签中
}),
],
样式文件的打包
npm i style-loader css-loader less-loader -D
{
test: /\.(css|less)$/,
use: ["style-loader", "css-loader", "less-loader"],
},
style-loader将打包的样式文件通过style标签放入页面(body前面),css-loader打包时先处理css文件,然后style-loader将文件放到页面中
链式调用,从后往前执行,数组中的顺序不能乱
样式文件的抽离与压缩
这个webpack5才支持有效,webpack4都不行
npm i mini-css-extract-plugin -D 2.42
npm i css-minimizer-webpack-plugin -D 3.1.1
mini-css-extract-plugin将css文件单独抽取出来,webpack默认是与js打包在一起的
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
plugins: [
new MiniCssExtractPlugin({
filename: "styles/[contenthash].css",
}),
],
{
test: /\.(css|less)$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
},
css-minimizer-webpack-plugin,用于css文件压缩
const CssMinimizerWebpackPlugin = require("css-minimizer-webpack-plugin");
optimization: {
minimizer: [new CssMinimizerWebpackPlugin()],
},
1》asset/resource
可以发送单独的一个文件,并导出url;
两种设置打包的方式
第一种方式:output配置中的assetModuleFilename
output: {
filename: "bundle.js",
path: __dirname + "/test",
clean: true,
assetModuleFilename: "images/[contenthash][ext]",
},
第二种方式:module中的module–rules–type、generator
module: {
rules: [
{
test: /\.jpg$/,
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]",// 设置生成的目录即名称,根据文件名生成哈希值并保持原来的扩展名
},
},
],
}
第二种设置方式优先级高于第一种
2》asset/inline
导出一个资源的 data URI
module: {
rules: [
{
test: /\.jpg$/,
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]",// 设置生成的目录即名称,根据文件名生成哈希值并保持原来的扩展名
},
},
],
}
3》asset/source
文本文件,比如我们的txt文件
module: {
rules: [
{
test: /\.txt$/,
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]",// 设置生成的目录即名称,根据文件名生成哈希值并保持原来的扩展名
},
},
],
}
4》asset
通用资源,在导出一个资源data URI和发送一个单独的文件并导出URL之间做选择
在inline和resource之间做选择,根据文件大小,自动决定是inline还是resource的打包方式
module:{
rules:[{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type:"asset/resource"
}]
}
json5文件和json很相似,可以当作json的升级版
npm i json5 -D
const json5=require("json5")
{
test: /\.json5$/,
type: "json",
parser: {
parse: json5.parse,
},
},
es6代码处理
因为有些老的浏览器不支持es6语法,所以我们要借助babel-load,将es6转为更低版本的es语法
npm i babel-loder @babel/core @babel/presest-env -D
babel-loder: 解析es6的桥梁
@babel/core:babel核心模块,babel-loader必须搭配它才能发挥作用
@babel/presest-env: babel预设,一些babel插件的集合
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
此时打包报错 regeneratorRuntime is not defined,原因是我们使用了promise,而转换它我们需借助其他插件
npm i @babel/runtime -D
npm i @babel/plugin-transform-runtime -D
修改下配置
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
plugins: [["@babel/plugin-transform-runtime"]],
},
},
},
生产环境下js的压缩
webpack5已内置,只需引入,添加配置
npm i terser-webpack-plugin -D // 由于webapack5已经内置这个插件了,所以不需要重新安装了
const TerserPlugin=require("terser-webpack-plugin")
optimization:{
minimizer:{
new TerserPlugin()
}
}
方法1:使用entry配置手动分离代码
问题:公共的引用会被打包到不同的chunk,那么将导致重复的引用重复打包,而且包体积变大
entry: {
index: "./src/index.js",
es6: "./src/es6.js",
sameJs: "./src/sameModule.js",
},
output:{
filename: "[name].bundle.js",
}
我们多个js文件打包,如果有相同的引用,那么会导致重复的打包
方法2:使用Entry dependencies或者SplitChunksPlugin
打包后多出一个chunk,是公共的lodash,不会重复
写法1:
entry: {
index: {
import: "./src/index.js",
dependOn: "shared",
},
es6: "./src/es6.js",
sameJs: {
import: "./src/sameModule.js",
dependOn: "shared",
},
shared: "lodash",
}
output:{
filename: "[name].bundle.js",
}
写法2:splitChunks
entry: {
index: "./src/index.js",
es6: "./src/es6.js",
sameJs: "/src/sameModule.js",
},
module中添加配置:
optimization: {
minimizer: [new CssMinimizerWebpackPlugin()],
splitChunks: {
chunks: "all",
},
},
方法3:通过模块化的内联函数调用来分离代码
懒加载、按需加载
预热加载模块
配置输出文件的重命名
如果我们在打包输出的时候,更改了文件内容,而打包的文件名没有改,那么浏览器会走缓存,然后内容不会即使地得到更新,所以我们需要在打包时对修改了内容的文件重命名
output: {
filename: "[name].[contenthash].js"
}
这种中括号表示不是写死的,contenthash如果文件内容发生变化,那么contenthash就会改变,否则是不会变的
缓存第三方库
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},
的文件名没有改,那么浏览器会走缓存,然后内容不会即使地得到更新,所以我们需要在打包时对修改了内容的文件重命名
output: {
filename: "[name].[contenthash].js"
}
这种中括号表示不是写死的,contenthash如果文件内容发生变化,那么contenthash就会改变,否则是不会变的
缓存第三方库
optimization: {
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},