文章目录
一、默认入口和默认出口
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js // 可以先不配置,最后一步再加
|- /dist
|- index.html
|- /src
|- index.js
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>起步</title>
</head>
<body>
// 默认出口就是dist/main.js
// 这里是直接指定,包括使用插件默认也是引入dist/main.js
<script src="main.js"></script>
</body>
</html>
// 引入的包可以被识别的打包
import _ from "lodash";
function component() {
const element = document.createElement("div");
// lodash 现在使用 import 引入
element.innerHTML = _.join(["Hello", "webpack"], " ");
return element;
}
document.body.appendChild(component());
// 检查npm registry
npm config get registry
// 改成淘宝源的新地址,下载包更快,不容易出错
npm config set registry https://registry.npmmirror.com
// npm 开发依赖;只会在开发环境需要,不会打包到dist中
// 也就是package.json中的devDependencies
// --save-dev 简写 -D
npm i package --save-dev // 示意,不用安装
// npm 生产依赖;会打包到dist中,影响包的大小和打包速度
// 也就是package.json中的dependencies
// --save 简写 -S
npm i package --save // 示意,不用安装
npm init -y // y表示yes,跳过一步
npm i webpack webpack-cli -D
npm i lodash -S
// webpack.config.js
const path = require("path");
module.exports = {
entry: "./src/index.js", // 入口
output: { // 出口 // 输出文件
filename: "main.js",
// 注意这个dist是相对于文件夹根目录,也就是创建一个dist目录并且把输出文件放在里面
path: path.resolve(__dirname, "dist"),
},
};
二、资源配置
// style.css
.red {
color: red;
font-size: 20px;
}
// index.js
import _ from "lodash";
import "./style.css";
function component() {
const element = document.createElement("div");
// lodash 现在使用 import 引入
element.innerHTML = _.join(["Hello", "webpack"], " ");
element.classList.add("red");
return element;
}
document.body.appendChild(component());
const path = require("path");
module.exports = {
entry: "./src/index.js",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
// 正则,以.css文件结尾,$表示结尾,\表示转义
test: /\.css$/,
// 从右边的loader开始加载处理,返回结果给左边的继续处理
use: ["style-loader", "css-loader"],
},
],
},
};
// .style.css
.red {
color: red;
font-size: 20px;
height: 300px;
background: url('./logo.png'); // 增加图片的使用
}
// webpack.config.js中module.rules添加一条
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: 'asset/resource', // 这个type应该是webpack自带的插件进行处理
},
三、输出文件
3.1 多文件入口
// src/print.js
export default function print(msg = "Hello World") {
console.log(msg);
}
// index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>起步</title>
// index.html就在dist目录下,dist目录新增了两个出口文件print.js、index.js
<script src="./print.js"></script>
</head>
<body>
<script src="./index.js"></script>
</body>
</html>
// index.js
import _ from "lodash";
import "./style.css";
import print from "./print";
function component() {
const element = document.createElement("div");
// lodash 现在使用 import 引入
element.innerHTML = _.join(["Hello", "webpack"], " ");
element.classList.add("red");
const btn = document.createElement("button");
btn.innerHTML = "click me";
btn.onclick = print;
element.appendChild(btn);
return element;
}
document.body.appendChild(component());
// webpack.config.js
const path = require("path");
module.exports = {
// 配置多个入口,那么就会产生多个出口文件; 多个入口文件都会在index.html中单独引入
entry: {
index: "./src/index.js",
print: "./src/print.js",
},
output: {
filename: "[name].js", // name表示动态文件名,entry中指定的key
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
3.2 HtmlWebpackPlugin插件
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: "./src/index.js",
print: "./src/print.js", // 注意这个顺序,index.html中的引入顺序也是如此
},
output: {
// 增加contenthash值,是一个随机字符串
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
// 可能改造过配置文件,导致dist目录有之前构建的很多不需要文件,构建前清理一下dist目录
clean: true,
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
};
四、环境
4.1 环境变量
// package.json
// 这一条改成这个 增加打包的参数;在env对象里增加goal: local, production: true
// --progress 是增加进步条;--color增加颜色;打包时间长的时候出现;
"build": "webpack --env goal=local --env production --progress --color"
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 改造成匿名函数,这样可以获取参数
module.exports = (env, argv) => {
// env中增加goal和production属性; env是argv中的一个属性
console.log("env, argv", env, argv);
return {
// mode是指定模式,可以通过env参数来决定是什么模式
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
index: "./src/index.js",
print: "./src/print.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
};
};
// print.js
export default function print(msg = "Hello World") {
// 注意在一般文件中访问process或者process.env会报错,node只暴漏了process.env.NODE_ENV变量出来
// process.env.NODE_ENV就是webpack.config.js中的mode属性
console.log("process", process.env.NODE_ENV);
}
4.2 热更新
// package.json scripts增加
// webpack-dev-server --open 和 webpack serve --open 都是可以的;出现错误可以都试一下;
"start-dev": "webpack-dev-server --open --env production=false",
"start": "webpack serve --open --env production=false",
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (env, argv) => {
console.log("env, argv", env, argv);
return {
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
print: "./src/print.js",
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "/", // 解决静态资源加载路径问题
},
optimization: {
// runtimeChunk是模块关系文件,single表示这里打包成一个runtime名称的文件
runtimeChunk: "single",
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
// 开发模式下开启热更新
devServer: {
static: "./dist", // 插件寻找启动文件
hot: true, // 开启热更新
open: true, // 自动打开浏览器
port: 3000, // 端口号
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
};
五、代码分离
5.1 公共模块
// print.js
import _ from "lodash";
export default function print(msg = "Hello World") {
console.log("process", process.env.NODE_ENV, 1111);
console.log(_.join([1, 2, 3]));
}
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (env, argv) => {
console.log("env, argv", env, argv);
return {
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
print: "./src/print.js",
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "/", // 解决静态资源加载路径问题
},
optimization: {
runtimeChunk: "single",
// all 表示公共的依赖模块提取到各自的chunk中;
// 比如两个文件里引入了lodash,那么lodash会被打包lodash的chunk中
splitChunks: {
chunks: "all",
},
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
// 开发模式下开启热更新
devServer: {
static: "./dist", // 插件寻找启动文件
hot: true, // 开启热更新
open: true, // 自动打开浏览器
port: 3000, // 端口号
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
};
5.2 懒加载
index.js
import _ from "lodash";
import "./style.css";
// import print from "./print"; // 注释掉,使用动态导入 否则也不会单独打包
function component() {
const element = document.createElement("div");
// lodash 现在使用 import 引入
element.innerHTML = _.join(["Hello", "webpack"], " ");
element.classList.add("red");
const btn = document.createElement("button");
btn.innerHTML = "click me";
btn.onclick = (e) =>
//
import(/* webpackChunkName: "print" */ "./print").then((module) =>
module.default()
);
element.appendChild(btn);
return element;
}
document.body.appendChild(component());
// webpack.config.js
// 用5.1配置就可以了
5.3 预获取/预加载模块
预获取,空闲时进行;加载将来需要的资源
import(/* webpackPrefetch: true */ './path/to/LoginModal.js');
预加载,父 chunk 加载时以并行方式开始加载;加载当前路由下可能需要的资源
import(/* webpackPreload: true */ './path/to/LoginModal.js');
六、缓存
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (env, argv) => {
console.log("env, argv", env, argv);
return {
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "/", // 解决静态资源加载路径问题
},
optimization: {
// moduleIds 模块标识符,使模块更容易被缓存和重复使用;
// 项目中新增和删除文件,导致解析顺序发生变化,会导致vendor包变化; 创建唯一模块标识符
moduleIds: "deterministic",
runtimeChunk: "single",
// all 表示公共的依赖模块提取到各自的chunk中;
// 比如两个文件里引入了lodash,那么lodash会被打包lodash的chunk中
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
// node_modules下的包都打包到vendors这个chunk中
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
// 开发模式下开启热更新
devServer: {
static: "./dist", // 插件寻找启动文件
hot: true, // 开启热更新
open: true, // 自动打开浏览器
port: 3000, // 端口号
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
};
七、Tree Shaking
// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = (env, argv) => {
console.log("env, argv", env, argv);
return {
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "/", // 解决静态资源加载路径问题
},
optimization: {
// moduleIds 模块标识符,使模块更容易被缓存和重复使用;
// 项目中新增和删除文件,导致解析顺序发生变化,会导致vendor包变化; 创建唯一模块标识符
moduleIds: "deterministic",
runtimeChunk: "single",
// all 表示公共的依赖模块提取到各自的chunk中;
// 比如两个文件里引入了lodash,那么lodash会被打包lodash的chunk中
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
// node_modules下的包都打包到vendors这个chunk中
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
// tree shaking
// // 标记未使用的导出(代码级别),production模式下不会被打包进输出文件(代码体积会减少)
usedExports: true,
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
],
// 开发模式下开启热更新
devServer: {
static: "./dist", // 插件寻找启动文件
hot: true, // 开启热更新
open: true, // 自动打开浏览器
port: 3000, // 端口号
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
};
八、公共路径
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// 尝试使用环境变量,否则使用根路径; process.env.ASSET_PATH 默认值是undefined
const ASSET_PATH = process.env.ASSET_PATH || "/"; //
console.log("ASSET_PATH", process.env.ASSET_PATH, ASSET_PATH);
module.exports = (env, argv) => {
console.log("env, argv", env, argv);
return {
mode: "development", // 开发模式 development // 默认是 production 生产模式
// devtool 打包后的文件是压缩的不是源代码,报错了找不到错误位置,需要源代码映射
devtool: "inline-source-map", // 开发模式是 inline-source-map // 生产模式是 source-map
entry: {
index: "./src/index.js",
},
output: {
filename: "[name].[contenthash].js",
path: path.resolve(__dirname, "dist"),
clean: true,
publicPath: "/", // 解决静态资源加载路径问题
},
optimization: {
// moduleIds 模块标识符,使模块更容易被缓存和重复使用;
// 项目中新增和删除文件,导致解析顺序发生变化,会导致vendor包变化; 创建唯一模块标识符
moduleIds: "deterministic",
runtimeChunk: "single",
// all 表示公共的依赖模块提取到各自的chunk中;
// 比如两个文件里引入了lodash,那么lodash会被打包lodash的chunk中
splitChunks: {
chunks: "all",
cacheGroups: {
vendor: {
// node_modules下的包都打包到vendors这个chunk中
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all",
},
},
},
// tree shaking
// 标记未使用的导出(代码级别),production模式下不会被打包进输出文件(代码体积会减少)
usedExports: true,
},
plugins: [
new HtmlWebpackPlugin({
title: "Webpack Test",
}),
// 这可以帮助我们在代码中安全地使用环境变量
// 让你可以自己定义一些变量,在代码中使用
new webpack.DefinePlugin({
"process.env.ASSET_PATH": JSON.stringify("ASSET_PATH"),
}),
],
// 开发模式下开启热更新
devServer: {
static: "./dist", // 插件寻找启动文件
hot: true, // 开启热更新
open: true, // 自动打开浏览器
port: 3000, // 端口号
},
module: {
rules: [
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i, // i表示不区分大小写
type: "asset/resource", // 这个type应该是webpack自带的插件进行处理
},
],
},
};
};