1.webpack 是什么
webpack 是一种前端资源构建工具,一个静态模块打包器(module bundler)。
在webpack 看来, 前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
通常我们在讨论时,bundle 指的是所有模块都打包进入的单个文件,而 chunk 指的是按照某种规则的模块集合,chunk 的体积大于单个模块,同时小于整个 bundle
2 webpack 五个核心概念
2.1 Entry
入口(Entry):指示 webpack 以哪个文件为入口起点开始打包,分析构建内部依赖图。
2.2 Output
输出(Output):指示 webpack 打包后的资源 bundles 输出到哪里去,以及如何命名。
2.3 Loader
Loader:让 webpack 能够去处理那些非 JS 的文件,比如样式文件、图片文件(webpack 自身只理解
JS)
2.4 Plugins
插件(Plugins):可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,
一直到重新定义环境中的变量等。
Mode(模式):
指示webpack使用相应模式的配置。
npm i webpack webpack-cli -D 安装webpack
webpack --stats 查看详细的打包信息
npm uninstall webpack webpack-cli -g 全局卸载webpack
npx webpack //当当前文件夹中node_modules中没有webpack时就会去上一级找有没有webpack
3.自定义webpack
npx webpack --entry ./src/index.js --mode production
配置文件配置webpack
在项目根目录下新建一个webpack.config.js的文件。使用common.js的语法
//webpack.config.js
const path = require('path')
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "./dist")
},
mode: "none"
}
然后执行npx webpack
4.自动引入资源
插件plugins的作用
HtmlWebpackPlugin
npm i html-webpack-plugin -D //安装插件
配置HtmlWepackPlugin插件
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const { Template } = require('webpack')
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "./dist")
},
plugins: [
new HtmlWepackPlugin({
// 以现有的html模版页面打包
template: "./index.html",
// 打包后的html
filename: 'app.html',
// 在body中生成script标签
inject: 'body'
})
],
mode: "development",
}
清除之前的打包内容
output: {
filename: "bundle.js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "./dist"),
// 清除之前的打包内容
clean: true
},
5.搭建开发环境
sourceMap
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const { Template } = require('webpack')
module.exports = {
entry: "./src/index.js",
output: {
...
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
mode: "development",
}
实时编译
npx webpack --watch //--watch 参数会在源文件发生变动的时候起到自动执行wepack编译的效果
Webpack-dev-serve
提供了一个基本的web serve,具有实时重新加载的功能live reloading,当文件发生修改,浏览器侦听到文件的修改自动刷新
npm i webpack-dev-server -D //安装
npx webpack-dev-server // 启动
npx webpack-dev-server --open //启动 并自动打开浏览器
Wepack-dev-server 并没有真正输出任何物理文件,它把输出后的bundle文件放到了内存里
6.资源模块
asset module
asset module type
asset/rource
配置打包输出文件名
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const { Template } = require('webpack')
module.exports = {
entry: "./src/index.js",
output: {
// 配置打包输出文件名 contenthash哈希,ext文件名后缀
assetModuleFilename: 'images/[contenthash][ext]'
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
mode: "development",
}
模块匹配处理规则
module: {
rules: [
{
test: /.png$/,
type: "asset/resource",
//优先级高于output中assetModuleFilename的规则
generator: {
filename: "images/test.png"
}
}
]
},
asset/inline
{
test: /.svg$/,
// 将文件转成base64 data-url
type: "asset/inline",
},
asset/source
{
test: /.txt$/,
type: "asset/source",
},
asset
{
test: /.jpg$/,
// 在 "asset/resource" 和 // 文件base64 data-url之间选择
// 当大于8k会创建文件,可以调节临界值来作为是否要生成文件的依据
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 * 1024
}
}
},
7.管理资源
loader 加载器
处理样式文件
npm i css-loader -D //安装css
配置文件
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
module.exports = {
entry: "./src/index.js",
output: {
...
},
devtool: "inline-source-map",
plugins: [
...
],
devServer: {
static: './dist'
},
module: {
rules: [
...
//css-loader 加载css
{
// test: /.css$/,
// 先css-loader编译css文件,再用style-loader加载到页面上
// use: ["style-loader", "css-loader"]
test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,再用style-loader将style标签加载到 页面上的header标签下
use: ["style-loader", "css-loader", 'less-loader']
}
]
},
mode: "development",
}
npm i css-loader style-loader -D
// 解析less需要用到less-loader 和less-loader
npm i less-loader less -D
抽离和压缩css
npm i mini-css-extract-plugin -D //安装抽离插件
配置文件
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module.exports = {
entry: "./src/index.js",
output: {
...
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
new MiniCssExtractPlugin({
// 定义抽离后的css文件名
filename: 'styles/[contenthash].css'
})
],
devServer: {
...
},
module: {
rules: [
...
{
test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,
//再用MiniCssExtractPlugin.loader
//将样式抽离到单独的文件中,生成.css文件会在打包后的html新增link标签并且引入抽离的css文件
use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader']
}
]
},
mode: "development",
}
npm i css-minimizer-webpack-plugin -D // 安装压缩css
配置文件
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const MiniMiZerCssPlugin = require("css-minimizer-webpack-plugin")
module.exports = {
entry: "./src/index.js",
output: {
filename: "bundle.js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "./dist"),
// 清除之前的打包内容
clean: true,
// 配置打包输出文件名 contenthash哈希,ext文件名后缀
assetModuleFilename: 'images/[contenthash][ext]'
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
devServer: {
static: './dist'
},
module: {
...
},
// 优化
optimization: {
minimizer: [
new MiniMiZerCssPlugin()
]
},
// 压缩需要将mode改为production
mode: "production",
}
在css中加载图片
// style.css
.block-bg {
border-color: url("./asset/logo.svg") !important;
}
//index.js
block.classList.add("block-bg")
加载font字体
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const MiniMiZerCssPlugin = require("css-minimizer-webpack-plugin")
module.exports = {
entry: "./src/index.js",
output: {
...
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
devServer: {
static: './dist'
},
module: {
rules: [
...
{
test: /.(woff|woff2|eot|ttf|otf)$/,
type: "asset/resource"
}
]
},
// 优化
optimization: {
...
},
mode: "development",
}
加载数据
npm i csv-loader xml-loader -D //安装loader
...
module.exports = {
entry: "./src/index.js",
output: {
...
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
devServer: {
static: './dist'
},
module: {
rules: [
...
// 会转成数组
{
test: /.(csv|tsv)$/,
use: "csv-loader"
},
// 会转成obj
{
test: /.xml$/,
use: "xml-loader"
}
]
},
mode: "development",
}
自定义的JSON模块parser
npm i yaml toml json -D //
// 引入yaml
const yaml = require("yaml")
module.exports = {
entry: "./src/index.js",
output: {
...
},
// 通过source-map可以追踪错误源码的出处
devtool: "inline-source-map",
plugins: [
...
],
devServer: {
static: './dist'
},
module: {
rules: [
...
{
test: /.yaml$/,
type: "json",
parser: {
parse: yaml.parse
}
}
]
},
}
8.使用babel-loader
ES6语法转化 使低版本的浏览器也能执行es6语法!
npm install babel-loader@8.0.0-beta.0 @babel/core @babel/preset-env
// 配置文件
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
9.代码分离
入口起点
配置文件
entry: {
// 两个打包入口
index: "./src/index.js",
another: "./src/another-module.js"
},
output: {
// 打包后的名字
filename: "[name].bundle.js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "./dist"),
// 清除之前的打包内容
clean: true,
// 配置打包输出文件名 contenthash哈希,ext文件名后缀
assetModuleFilename: 'images/[contenthash][ext]'
},
防止重复
多入口配置文件1
entry: {
index: {
import: './src/index.js',
// 依赖shared模块
dependOn: "shared"
},
another: {
import: './src/another-module.js',
// 将共享的文件定义出来
dependOn: "shared"
},
//将其他模块都用到的依赖单独抽离出来
shared: "lodash"
},
使用webpack内置插件split-chunks-Plugin
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
module.exports = {
entry: {
index: './src/index.js',
another: './src/another-module.js'
},
optimization: {
splitChunks: {
chunks: "all"
}
}
}
动态导入
//利用Es6提供的import语法
async function getComponent() {
const element = document.createElement('div');
const { default: _ } = await import('lodash');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
getComponent().then((ele) => {
document.body.appendChild(ele)
})
应用
懒加载
const btn = document.createElement("button")
btn.textContent = "点击执行加法运算"
btn.addEventListener("click", async () => {
const { add } = await import(/*webpackChunkName:'math'*/"./math")
console.log(add(4, 5))
})
document.body.appendChild(btn)
btn.addEventListener("click", async () => {
//webpackPrefetch:true 告诉浏览器进行预获取在网络空闲时
const { add } = await import(/*webpackChunkName:'math',webpackPrefetch:true*/"./math")
console.log(add(4, 5))
})
document.body.appendChild(btn)
btn.addEventListener("click", async () => {
//webpackPreload:true 告诉浏览器进行预获取在网络空闲时
const { add } = await import(/*webpackChunkName:'math',webpackPreload:true*/"./math")
console.log(add(4, 5))
})
document.body.appendChild(btn)
10.缓存
通过contenthash打包生成文件名,来进行缓存处理
output: {
// [name] subsitution 可替换的模版字符串
filename: "[name].[contenthash].js",
//path.resolve(__dirname,"xxx")__dirname当前文件路径
path: path.resolve(__dirname, "dist"),
// 清除之前的打包内容
clean: true,
// 配置打包输出文件名 contenthash哈希,ext文件名后缀
assetModuleFilename: 'images/[contenthash][ext]'
},
缓存第三库
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
将所有的js文件放到一个文件夹下
output: {
// 全部放到一个文件夹下
filename: 'scripts/[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
11.拆分开发环境和生产环境配置
公共路径
output: {
filename: 'scripts/[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
// 指定资源的基础路径
publicPath: "http://localhost:8080/"
},
环境变量
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
module.exports = (env) => {
console.log(env)
return {
mode: env.production ? "production" : "development",
...
}
}
压缩代码
npm i terser-webpack-plugin -D //
optimization: {
minimizer: [
new TerserPlugin()
],
},
12.拆分配置文件
//根目录下新建/config/webpack.config.dev.js
//执行 npx webpack --config config/webpack.config.dev.js
// 修改路径
output: {
filename: 'scripts/[name].js',
path: path.resolve(__dirname, '../dist'),
clean: true,
},
开发环境配置
// /config/webpack.config.dev.js
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
console.log("webpack.config.dev.js", path.resolve(__dirname, "../dist"))
module.exports = {
entry: {
index: './src/index.js',
another: "./src/another-module.js"
},
output: {
filename: 'scripts/[name].js',
path: path.resolve(__dirname, '../dist'),
clean: true,
},
mode: "development",
devtool: "inline-source-map",
plugins: [
new HtmlWepackPlugin({
// 以现有的html模版页面打包
template: "./index.html",
// 打包后的html
filename: 'app.html',
// 在body中生成script标签
inject: 'body'
})
],
devServer: {
static: './dist'
},
module: {
rules: [
{
test: /.png$/,
// 文件路径
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]"
}
},
{
test: /.svg$/,
// 文件base64 data-url
type: "asset/inline",
},
{
test: /.txt$/,
type: "asset/source",
},
{
test: /.jpg$/,
// 在 "asset/resource" 和 // 文件base64 data-url之间选择
// 当大于8k会创建文件,可以调节临界值来作为是否要生成文件的依据
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 * 1024
}
}
},
{
test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,
//再用MiniCssExtractPlugin.loader
//将样式抽离到单独的文件中,生成.css文件会在打包后的html新增link标签并且引入抽离的css文件
use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader']
},
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
}
生产环境配置
// /config/webpack.config.prod.js
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const MiniMiZerCssPlugin = require("css-minimizer-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")
module.exports = {
entry: {
index: './src/index.js',
another: "./src/another-module.js"
},
output: {
filename: 'scripts/[name].[contenthash].js',
path: path.resolve(__dirname, '../dist'),
clean: true,
publicPath: "http://localhost:8080/"
},
mode: "production",
module: {
rules: [
{
test: /.png$/,
// 文件路径
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]"
}
},
{
test: /.svg$/,
// 文件base64 data-url
type: "asset/inline",
},
{
test: /.txt$/,
type: "asset/source",
},
{
test: /.jpg$/,
// 在 "asset/resource" 和 // 文件base64 data-url之间选择
// 当大于8k会创建文件,可以调节临界值来作为是否要生成文件的依据
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 * 1024
}
}
},
{
test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,
//再用MiniCssExtractPlugin.loader
//将样式抽离到单独的文件中,生成.css文件会在打包后的html新增link标签并且引入抽离的css文件
use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader']
},
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
plugins: [
new HtmlWepackPlugin({
// 以现有的html模版页面打包
template: "./index.html",
// 打包后的html
filename: 'app.html',
// 在body中生成script标签
inject: 'body'
})
],
optimization: {
minimizer: [
new TerserPlugin(),
new MiniMiZerCssPlugin()
],
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
}
启动webpack-dev-serve
npx webpack serve --config config/webpack.config.dev.js --open
npm 脚本
//package.json
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"start": "webpack serve --config config/webpack.config.dev.js --open",
"build": "webpack --config config/webpack.config.prod.js"
},
// 可以关闭删除时的打包提示信息warning
performance: {
hints: false
}
提取公共配置
const path = require('path')
const HtmlWepackPlugin = require("html-webpack-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
console.log("webpack.config.common.js", path.resolve(__dirname, "../dist"))
module.exports = {
entry: {
index: './src/index.js',
another: "./src/another-module.js"
},
output: {
path: path.resolve(__dirname, '../dist'),
clean: true,
// 配置打包输出文件名 contenthash哈希,ext文件名后缀
assetModuleFilename: 'images/[contenthash][ext]'
},
plugins: [
new HtmlWepackPlugin({
// 以现有的html模版页面打包
template: "./index.html",
// 打包后的html
filename: 'app.html',
// 在body中生成script标签
inject: 'body'
})
],
module: {
rules: [
{
test: /.png$/,
// 文件路径
type: "asset/resource",
generator: {
filename: "images/[contenthash][ext]"
}
},
{
test: /.svg$/,
// 文件base64 data-url
type: "asset/inline",
},
{
test: /.txt$/,
type: "asset/source",
},
{
test: /.jpg$/,
// 在 "asset/resource" 和 // 文件base64 data-url之间选择
// 当大于8k会创建文件,可以调节临界值来作为是否要生成文件的依据
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 4 * 1024 * 1024
}
}
},
{
test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,
//再用MiniCssExtractPlugin.loader
//将样式抽离到单独的文件中,生成.css文件会在打包后的html新增link标签并且引入抽离的css文件
use: [MiniCssExtractPlugin.loader, "css-loader", 'less-loader']
},
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\/]node_modules[\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
}
npm i webpack-merge -D // 安装依赖
/config/webpack.config.js
const { merge } = require("webpack-merge")
const commonConfig = require("./webpack.config.common")
const prodConfig = require("./webpack.config.prod")
const devConfig = require("./webpack.config.dev")
module.exports = (env) => {
switch (true) {
case env.development:
return merge(commonConfig, devConfig)
case env.production:
return merge(commonConfig, prodConfig)
default:
new Error("no matching configuration was found")
}
}
// 修改脚本
"scripts": {
"start": "webpack serve --config config/webpack.config.js --env development",
"build": "webpack --config config/webpack.config.js --env production"
},
13.sourceMap
1.默认 "eval"
// webpack.config.js
2.devtool:"source-map", // 在末尾加 //# sourceMappingURL=main.js.map
// main.js.map
{
"version": 3,
"file": "main.js",
"mappings": "AAAAA,QAAQC,IAAI",
"sources": [
"webpack://01-sourcemap/./app.js"
],
"sourcesContent": [
"console.log("hello webpack")"
],
"names": [
"console",
"log"
],
"sourceRoot": ""
}
3.devtool:"hidden-source-map", // 在末尾不追加链接 在控制台无法看到源代码行数
// main.js.map
{
"version": 3,
"file": "main.js",
"mappings": "AAAAA,QAAQC,IAAI",
"sources": [
"webpack://01-sourcemap/./app.js"
],
"sourcesContent": [
"console.log("hello webpack")"
],
"names": [
"console",
"log"
],
"sourceRoot": ""
}
4.devtool:"inline-source-map", //生产一个dataURL形式的sourceMappingURL 可以锁定代码行数 不生成main.js.map
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsIm1hcHBpbmdzIjoiQUFBQUEsUUFBUUMsSUFBSSIsInNvdXJjZXMiOlsid2VicGFjazovLzAxLXNvdXJjZW1hcC8uL2FwcC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZyhcImhlbGxvIHdlYnBhY2tcIikiXSwibmFtZXMiOlsiY29uc29sZSIsImxvZyJdLCJzb3VyY2VSb290IjoiIn0=
5.devtool:"hidden-source-map", //每个module会通过eval()来执行,并生成dataURL形式的sourceMappingURL
eval("console.log("hello webpack")//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9hcHAuanMuanMiLCJtYXBwaW5ncyI6IkFBQUEiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8wMS1zb3VyY2VtYXAvLi9hcHAuanM/OWE3OCJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zb2xlLmxvZyhcImhlbGxvIHdlYnBhY2tcIikiXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./app.js\n");
6.devtool:"cheap-source-map" //生成一个没有列信息的source-map,不包含loader的sourcemap 追踪不到代码行数
{
"version": 3,
"file": "main.js",
//只保留行信息
"mappings": ";;;;;AAAA",
"sources": [
"webpack://01-sourcemap/./app.js"
],
"sourcesContent": [
"console.log("hello webpack")"
],
"names": [],
"sourceRoot": ""
}
7.devtool:"cheap-module-source-map" //生成一个没有列信息的source-map,不包含loader的sourcemap 可以追踪代码行数
14.devServer
npx webpack serve // 启动开发服务器
配置文件
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: "./app.js",
output: {
publicPath: "/"
},
devServer: {
static: path.resolve(__dirname, './dist'),
// 是否进行压缩
compress: true,
// 服务器端口
port: 3000,
host: "0.0.0.0",
// 在Response Headers 中添加信息
headers: {
"x-access-token": 'abc123'
},
proxy: {
// 访问/api开头的借口,就会转发到http://localhost:9000
"/api": "http://localhost:9000"
},
// 使用https
// https: true
http2: true,
// 路径失败跳回主页
historyApiFallback: true
},
plugins: [
new HtmlWebpackPlugin()
],
}
15.模块热替换与热加载
const path = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
const { template } = require("lodash")
module.exports = {
mode: "development",
entry: "./app.js",
devServer: {
// 模块热替换
hot: false,
// 热加载
liveReload: false
},
plugins: [
new HtmlWebpackPlugin(
{
template: "./index.html"
}
)
],
module: {
rules: [
{
test: /.css$/,
// 先css-loader编译css文件,再用style-loader加载到页面上
use: ["style-loader", "css-loader"]
// test: /.(css|less)$/,
// 先用less-loader解析less语法,然后用css-loader编译css文件,再用style-loader将style标签加载到 页面上的header标签下
// use: ["style-loader", "css-loader", 'less-loader']
}
]
},
}
16.EsLint
npm i eslint -D // 安装 也可以使用。npm init @eslint/config
// 配置eslint
chengpeng@chengpeng 04-eslint % npx eslint --init
You can also run this command directly using 'npm init @eslint/config'.
npx: 41 安装成功,用时 4.251 秒
? How would you like to use ESLint? …
To check syntax only
❯ To check syntax and find problems
To check syntax, find problems, and enforce code style
npx eslint ./src //检测代码规范
配置文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ESLintPlugin = require('eslint-webpack-plugin');
const { resolve } = require('path');
module.exports = {
mode: 'development',
entry: './src/app.js',
plugins: [
new HtmlWebpackPlugin(),
new ESLintPlugin({
extensions: ['js'],
context: resolve('src'),
exclude: '/node_modules',
fix: true,
}),
],
};
husky
npm i husky -D //安装依赖
npx husky install //安装husky
在.husky文件下新建一个pre-commit文件
内容为
npx eslint ./src
修改文件权限
chmod +x .husky/pre-commit
然后在git commit 的时候就会执行这个脚本
17.模块和依赖
模块解析
import Header from '/src/components/header' // 绝对路径
import Header from './components/header' //相对路径
import _ from 'lodash' // 模块路径
const {resolve} = require('path')
module.exports = {
mode:"development",
entry:"./src/app.js",
// 模块解析
resolve:{
alias:{
"@":resolve(__dirname,"./src")
},
extensions:['.json','.js']
},
}
External
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode:"development",
entry:"./app.js",
plugins: [
new HtmlWebpackPlugin()
],
externals:{
jquery: [
"https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js",
"$"
]
},
externalsType:'script'
}
18.PostCss 与Css模块
npm i style-loader css-loader postcss-loader -D // 安装loader
npm i autoprefixer -D // 安装插件
npm i postcss-nested -D。// 安装插件
第一步:在package.json 在package.json使用 browserslist 字段
"browserslist": [
">1%",
"last 2 versions"
]
第二步:新增 postcss.config.js
module.exports = {
plugins: [
//Autoprefixer是一款基于PostCSS插件,用于解析CSS并使用Can I Use中的值向CSS规则添加供应商前缀 。它是 Google 推荐的,可以实现css3代码自动补全,也可以运用到sass、less中
require('autoprefixer'),
// 支持嵌套语法
require("postcss-nested")
]
}
// 配置文件
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: {
app: './src/app.js',
},
plugins: [
new HtmlWebpackPlugin(),
],
module: {
rules: [
{
test: /.css$/,
use: [
"style-loader",
// css 模块化
{
loader: "css-loader",
options: {
modules: true
}
},
"postcss-loader"
]
}
]
}
}
19.Web Works
20.TypeScript
npm i typescript ts-loader //
npx tsc --init // init 生产tsconfig.json
打开 "outDir": "./", 修改为 "outDir": "./dist",
配置文件
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: "./src/app.ts",
output: {
filename: "bundle.js",
path: path.resolve(__dirname, "dist")
},
plugins: [
new HtmlWebpackPlugin()
],
devtool: "inline-source-map",
module: {
rules: [
{
test: /.ts$/,
use: "ts-loader",
exclude: /node_modules/,
}
]
},
resolve: {
//模块解析优先级
extensions: ['.ts', '.js']
}
}
ts使用lodash
npm i lodash @types/lodash
多页应用
自定义html模版
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = {
mode: "development",
entry: {
main: {
//打包入口
import: [
"./src/app.js",
"./src/app2.js",
],
// 依赖的模块
dependOn: "lodash",
// 打包路径
filename: "chanel1/[name].js",
},
main2: {
import: "./src/app3.js",
dependOn: "lodash",
filename: "chanel2/[name].js",
},
lodash: {
import: "lodash",
filename: "common/[name].js",
},
},
output: {
clean: true,
},
plugins: [
// 模版一
new HtmlWebpackPlugin({
//模版title
title: "zcc大猪头",
//打包模版
template: "./index.html",
//js位置
inject: "body",
//打包路径
filename: "chanel1/index.html",
//需要的chunk
chunks: ["main", "lodash"]
}),
//模版二
new HtmlWebpackPlugin({
title: "zcc2大猪头",
template: "./index2.html",
inject: "body",
filename: "chanel2/index2.html",
chunks: ["main2", "lodash"],
publicPath: "http:baidu.com"
})
],
devtool: "inline-source-map",
}
Tree-shaking
const HtmlWwbpackPlugin = require('html-webpack-plugin');
module.exports = {
// mode: "development",
mode: "production",
entry: "./src/app.js",
plugins: [
new HtmlWwbpackPlugin()
],
optimization: {
usedExports: true
}
}
webpack 是不能百分之百tree-shaking的
"sideEffects": [
"*.css",
"*.g.js"
],
//告诉webpack .css 和.g.js不能删除
PWA
Shimming
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack')
module.exports = {
mode: "development",
entry: "./src/index.js",
plugins: [
new HtmlWebpackPlugin(
{ title: 'Progressive Web Application' }
),
new webpack.ProvidePlugin({
_: "lodash"
})
],
module: {
rules: [
// 细粒度shimming
{
test: require.resolve("./src/index.js"),
use: "imports-loader?wrapper=window"
},
// 全局导出
{
test: require.resolve("./src/globals.js"),
use: "exports-loader? type=commonjs&exports=file,multiple|helpers.parse|parse"
},
]
}
}
全局exports
polyfill
npm i babel-loader @babel/core @babel/preset-env -D
npm install core-js@3 -D
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
// mode: 'production',
entry: "./src/index.js",
plugins: [
new HtmlWebpackPlugin(
{ title: 'Progressive Web Application' }
),
],
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
"@babel/preset-env",
{
// polyfill 的目标浏览器
targets: [
"last 1 version",
"> 1%"
],
useBuiltIns: 'usage',
corejs: 3
}
]
]
}
}
}
]
}
}