一、搭建 webpack 基础环境
- 初始化环境
npm init -y
- 安装环境依赖
npm install webpack webpack-cli cross-env -D
- 在 package.json 中修改 scripts
"scripts": {
"dev": "cross-env NODE_ENV=development webpack --config ./webpack.config.js --watch --progress --color ",
"build": "cross-env NODE_ENV=production webpack --config ./webpack.config.js --progress --color "
},
- 新建入口文件 src/index.js
consle.log("hello world");
- 创建 webpack.config.js 配置文件
var path = require("path");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-budle.js",
},
mode: process.env.NODE_ENV,
module: {
rules: [],
},
};
- 打包测试
npm run dev
npm run build
二、javascript 代码转化
ES6+ 转化为 ES5
- 安装依赖
babel-loader:babel 语法转化工具
@babel/core:babel 核心工具
@babel/preset-env:babel 预设,限定 babel 语法转化的范围,指定兼容的浏览器版本
npm install babel-loader @babel/core @babel/preset-env -D
- 修改 webpack.config.js 配置文件
var path = require("path");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-budle.js",
},
mode: process.env.NODE_ENV,
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
},
},
},
],
},
};
- 在 package.json 中新增浏览器兼容范围 browserslist 属性
配合 @babel/preset-env 使用
"browserslist": [
"Android 4.1",
"iOS 7.1",
"ie >= 8",
"last 8 Chrome versions",
"last 5 Firefox versions",
"Safari >= 6",
"> 1%"
]
- 新建入口文件 src/index.js
const list = ["a", "b", "c"];
const listA = list.map((item) => item + "A");
console.log(listA);
const array = [1, 2, 3, 4, 1, 2, 3];
const set = new Set(array);
const newArray = Array.from(set);
console.log(newArray);
- 打包测试
npm run build
- 在 dist/app-budile.js 中查看结果
实际代码是压缩的,此处经过代码格式化展开查看效果,发现只是处理了变量声明和箭头函数,但是 ES6 API 未处理
!(function () {
var o = ["a", "b", "c"].map(function (o) {
return o + "A";
});
console.log(o);
var n = new Set([1, 2, 3, 4, 1, 2, 3]),
r = Array.from(n);
console.log(r);
})();
- 安装垫片处理 ES6 API
@babel/plugin-transform-runtime @babel/runtime-corejs3 core-js:组合垫片,转化 babel-loader 无法转化的 ES6+ API
npm install @babel/plugin-transform-runtime @babel/runtime-corejs3 core-js -D
- 修改 webpack.config.js 配置文件
const path = require("path");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-budle.js",
},
mode: process.env.NODE_ENV,
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: "3",
},
],
],
plugins: [
[
"@babel/plugin-transform-runtime",
{
corejs: "3",
},
],
],
},
},
},
],
},
experiments: {
topLevelAwait: true, // 开启 async await 转化,默认 false
asyncWebAssembly: true,
},
};
- 新建入口文件 src/index.js
const list = ["a", "b", "c"];
const listA = list.map((item) => item + "A");
console.log(listA);
const array = [1, 2, 3, 4, 1, 2, 3];
const set = new Set(array);
const newArray = Array.from(set);
console.log(newArray);
async function getdata() {
return new Promise((resolve, reject) => {
resolve("hello world");
});
}
const data = await getdata();
console.log(data);
- 打包测试
npm run build
- 在 dist/app-budile.js 中查看结果,发现代码是压缩的,且 ES6+ API 已经不存在
运行 node ./dist/app-budle.js ,发现功能正常,完成代码转化
[ 'aA', 'bA', 'cA' ]
[ 1, 2, 3, 4 ]
hello world
三、javascript 代码压缩 和 Tree Shaking
webpack5 生产环境默认支持代码压缩、公共代码整合 和 Tree Shaking,通过 optimization 选项的属性来控制
- 安装依赖
terser-webpack-plugin:打包时不生成 LICENSE.txt 文件
npm install terser-webpack-plugin -D
- 新建入口文件 src/index.js
const list = ["a", "b", "c"];
const listA = list.map((item) => item + "A");
console.log(listA);
const array = [1, 2, 3, 4, 1, 2, 3];
const set = new Set(array);
const newArray = Array.from(set);
console.log(newArray);
async function getdata() {
return new Promise((resolve, reject) => {
resolve("hello world");
});
}
const data = await getdata();
console.log(data);
const aaaaa = 123456;
- 修改 webpack.config.js 配置文件
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-budle.js",
},
mode: process.env.NODE_ENV,
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: "3",
},
],
],
plugins: [
[
"@babel/plugin-transform-runtime",
{
corejs: "3",
},
],
],
},
},
},
],
},
experiments: {
topLevelAwait: true, // 开启 async await 转化,默认 false
asyncWebAssembly: true,
},
optimization: {
usedExports: true, // 配合实现 Tree Shaking,,默认 true 开启
concatenateModules: true, // 公共代码整合,生产环境下被启用
minimize: true, // 在生成环境是否开启js代码压缩和Tree Shaking,默认 true 开启
minimizer: [
new TerserPlugin({
extractComments: false, // 默认:true,当 minimize为true 打包时会生成注释文件,参数为 false 不生成注释文件
}),
],
},
};
- 打包测试
npm run build
- 在 dist/app-budile.js 中查看结果
发现代码是压缩的,无法找到 123456、说明 js 代码压缩和 Tree Shaking 生效,且不生成 app-budle.js.LICENSE.txt 文件
四、javascript 代码分割 和 懒加载
webpack 执行异步懒加载的代码,在打包时会进行代码分割
webpack 懒加载的方式有两种,一种是通过 CommonJS 规范的 require.ensure(),一种是 ESModel 规范的 import()
- webpack.config.js 配置文件不变
const path = require("path");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: {
app: "./src/index.js",
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name]-budle.js",
},
mode: process.env.NODE_ENV,
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: [
[
"@babel/preset-env",
{
useBuiltIns: "usage",
corejs: "3",
},
],
],
plugins: [
[
"@babel/plugin-transform-runtime",
{
corejs: "3",
},
],
],
},
},
},
],
},
experiments: {
topLevelAwait: true, // 开启 async await 转化,默认 false
asyncWebAssembly: true,
},
optimization: {
usedExports: true, // 配合实现 Tree Shaking,,默认 true 开启
concatenateModules: true, // 公共代码整合,生产环境下被启用
minimize: true, // 在生成环境是否开启js代码压缩和Tree Shaking,默认 true 开启
minimizer: [
new TerserPlugin({
extractComments: false, // 当 minimize为true 打包时会生成注释文件,此参数为 false 不生成注释文件,默认:true
}),
],
},
};
- 新建入口文件 src/index.js
// 同步执行,打包后不生成新 budle
import listA from "./map.js";
console.log(listA);
// require.ensure() 异步执行,打包后生成新 budle
require.ensure(
[],
function () {
const set = require("./set.js");
console.log(set.default);
},
"set"
);
// ESModel import() 异步执行,打包后生成新 budle
import(/* webpackChunkName: "async" */ "./async.js").then((data) =>
console.log(data.default)
);
const aaaaa = 123456;
console.log(aaaaa);
- 新建测试文件 src/async.js、src/map.js、src/set.js 代码如下
// src/async.js
async function getdata() {
return new Promise((resolve, reject) => {
resolve("async await");
});
}
const data = await getdata();
export default data;
// src/map.js
const list = ["m", "a", "p"];
const listA = list.map((item) => item + "A");
export default listA;
// src/set.js
const array = [1, 2, 3, 4, 1, 2, 3];
const set = new Set(array);
const newArray = Array.from(set);
export default newArray;
- 新建 src/index.html 模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<script src="../dist/app-budle.js"></script>
<body></body>
</html>
- 打包
npm run build
- 在浏览器打开 src/index.html 查看结果
通过 Network 查看代码分割情况,通过 Console 控制台查看同步异步执行效果
['mA', 'aA', 'pA'] // 同步引入执行
123456 // 同步执行
[1, 2, 3, 4] // require.ensure 异步执行
async await // import 异步执行
网友评论