⼀、webpack 简介

1.1 webpack 是什么

webpack 是⼀种前端资源构建⼯具,⼀个静态模块打包器(module bundler)。 在 webpack 看来, 前端的所有资源⽂件(js/json/css/img/less/…)都会作为模块处理。 它将根据模块的依赖关系进⾏静态分析,打包⽣成对应的静态资源(bundle)。 官⽹:https://webpack.js.org/

前端资源构建⼯具:主要理解⼀下这个前端资源是哪些资源。这些前端资源就是浏览器不认识的 web 资源, ⽐如sass、less、ts,包括 js ⾥的⾼级语法。这些资源要能够在浏览器中正常⼯作,必须⼀⼀经过编译处理。⽽ webpack 就是可以集成这些编译⼯具的⼀个总的构建⼯具。静态模块打包器:静态模块就是 web 开发过程中的各种资源⽂件,webpack 根据引⽤关系,构建⼀个依赖关系图,然后利⽤这个关系图将所有静态模块打包成⼀个或多个 bundle 输出。

1.2 为什么我们需要 webpack

web 开发时调⽤后端接⼝跨域,需要其他⼯具代理或者其他⽅式规避。改动代码后要⼿动刷新浏览器,如果做了缓存还需要清缓存刷新。因为 js 和 css 的兼容性问题,很多新语法学习了却不能使⽤,⽆论是开发效率和个⼈成⻓都受影响。打包问题。需要使⽤额外的平台如 jekins 打包,⾃⼰编写打包脚本,对各个环节如压缩图⽚,打包 js、打包 css 都要⼀⼀处理。

1.3 webpack 五个核⼼概念

1.3.1 Entry

⼊⼝(Entry)指示 webpack 以哪个⽂件为⼊⼝起点开始打包,分析构建内部依赖图。

// string⽅式: 单⼊⼝,打包形成⼀个trunk,输出⼀个buldle⽂件。trunk的名称默认是main.js

entry: "./src/index.js"

// array⽅式:多⼊⼝,所有⼊⼝⽂件最终只会形成⼀个trunk,输出出去只有⼀个bundle⽂件

entry: ["./src/index.js", "./src/test.js"]

// object:多⼊⼝,有⼏个⼊⼝⽂件就形成⼏个trunk,输出⼏个bundle⽂件。此时trunk的名称就是对象key值

entry: {

index: "./src/index.js",

test: "./src/test.js",

}

//当构建项⽬包含多个⼦项⽬时,每次增加⼀个⼦系统都需要将⼊⼝⽂件写⼊webpack配置⽂件中,其实我们让webpack动态获取⼊⼝⽂件,

// 使⽤ glob 等⼯具使⽤若⼲通配符,运⾏时获得 entry 的条⽬

entry: glob.sync('./project/**/index.js').reduce((acc, path) => {

const entry = path.replace('/index.js', '')

acc[entry] = path

return acc

}, {})

//则会将所有匹配`./project/**/index.js`的⽂件作为⼊⼝⽂件进⾏打包,如果你想要增加⼀个⼦项⽬,仅仅需要在`project`创建⼀个⼦项⽬⽬录,并创建⼀个`index.js` 作为⼊⼝⽂件即可。

//这种⽅式⽐较适合⼊⼝⽂件不集中且较多的场景。

1.3.2 Output

输出(Output)指示 webpack打包后的资源 bundles 输出到哪⾥去,以及如何命名。

output: {

// 输出⽂件⽬录(将来所有资源输出的公共⽬录,包括css和静态⽂件等等)

path: path.resolve(__dirname, "dist"), //默认

// ⽂件名称(指定名称+⽬录)

filename: "[name].js", // 默认

// 或使⽤函数返回名(不常⽤)

// filename: (chunkData) => {

// return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js';

// },

// 所有资源引⼊公共路径前缀,⼀般⽤于⽣产环境,⼩⼼使⽤

// 打包⽣成的 index.html ⽂件⾥⾯引⽤资源的前缀

// 也为发布到线上资源的 URL 前缀

// 使⽤的是相对路径,默认为 ''

publicPath: "",

/*

⾮⼊⼝⽂件chunk的名称。所谓⾮⼊⼝即import动态导⼊形成的trunk或者optimization中的splitChunks提取的公共trunk

它⽀持和 filename ⼀致的内置变量

*/

chunkFilename: "[contenthash:10].chunk.js",

/* 当⽤ Webpack 去构建⼀个可以被其他模块导⼊使⽤的库时需要⽤到library */

library: {

name: "[name]",//整个库向外暴露的变量名

type: "window"//库暴露的⽅式

}

},

1.3.3 Loader

Loader让webpack能够去处理那些⾮JavaScript⽂件 (webpack⾃身只理解JavaScript)

rules: [

{

// 匹配哪些⽂件

test: /\.css$/,

// 使⽤哪些loader进⾏处理。执⾏顺序,从右⾄左,从下⾄上

use: [

// 创建style标签,将js中的样式资源(就是css-loader转化成的字符串)拿过来,添加到⻚⾯head标签⽣效

"style-loader",

// 将css⽂件变成commonjs⼀个模块加载到js中,⾥⾯的内容是样式字符串

"css-loader",

{

// css 兼容处理 postcss,注意需要在package.json配置browserslist

loader: "postcss-loader",

options: {

postcssOptions: {

ident: "postcss",

// postcss-preset-env插件:帮postcss找到package.json中的browserslist配置,根据配置加载指定的兼容性样式

plugins: [require("postcss-preset-env")()],

},

},

}],

},

{

test: /\.js$/,

// 注意需要在package.json配置browserslist,否则babel-loader不⽣效

// js兼容处理 babel

loader: "babel-loader", // 规则只使⽤⼀个loader时推荐写法

options: {

presets: [

[

"@babel/preset-env",// 预设:指示babel做怎么样的兼容处理

{

useBuiltIns: "usage", //按需加载

corejs: {

version: "3",

},

targets: "defaults",

}

]

]

}

},

/**

* Webpack5.0新增资源模块(asset module),它是⼀种模块类型,允许使⽤资源⽂件(字体,图标等)⽽⽆需配置额外loader。⽀持以下四个配置

* asset/resource 发送⼀个单独的⽂件并导出 URL。之前通过使⽤ file-loader 实现。

* asset/inline 导出⼀个资源的 data URI。之前通过使⽤ url-loader 实现。

* asset/source 导出资源的源代码。之前通过使⽤ raw-loader 实现。

* asset 在导出⼀个 data URI 和发送⼀个单独的⽂件之间⾃动选择。之前通过使⽤ url-loader,并且配置资源体积限制实现。

**/

// Webpack4使⽤file-loader实现

{

test: /\.(eot|svg|ttf|woff|)$/,

type: "asset/resource",

generator: {

// 输出⽂件位置以及⽂件名

filename: "fonts/[name][ext]"

},

},

// Webpack4使⽤url-loader实现

{

//处理图⽚资源

test: /\.(jpg|png|gif|)$/,

type: "asset",

generator: {

// 输出⽂件位置以及⽂件名

filename: "images/[name][ext]"

},

parser: {

dataUrlCondition: {

maxSize: 10 * 1024 //超过10kb不转base64

}

}

},

]

1.3.4 Plugins

插件(Plugins)可以⽤于执⾏范围更⼴的任务。插件的范围包括,从打包优化和压缩,⼀直到重新定义环境中的变量等。 它并不会影响 Webpack 的核⼼⼯作过程,只是 Webpack 为了提供⼀个强⼤的扩展能⼒,它为整个⼯作过程的每个环节都预制了⼀个钩⼦,也就是说我们可以通过插件往 Webpack ⼯作过程的任意环节植⼊⼀些⾃定义的任务,从⽽扩展 Webpack打包功能以外的能⼒。

// CleanWebpackPlugin帮助你在打包时⾃动清除dist⽂件,学习时使⽤⽐较⽅便

const { CleanWebpackPlugin } = require("clean-webpack-plugin");

// HtmlWebpackPlugin帮助你创建html⽂件,并⾃动引⼊打包输出的bundles⽂件。⽀持html压缩。

const HtmlWebpackPlugin = require("html-webpack-plugin");

// 该插件将CSS提取到单独的⽂件中。它会为每个trunk创造⼀个css⽂件。需配合loader⼀起使⽤

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// 该插件将在Webpack构建过程中搜索CSS资源,并优化\最⼩化CSS

const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

// vue-loader V15版本以上,需要引⼊VueLoaderPlugin插件,它的作⽤是将你定义过的js、css等规则应⽤到vue⽂件中去。

const { VueLoaderPlugin } = require('vue-loader')

module.exports = {

module: {

rules: [{

test: /\.vue$/,

loader: "vue-loader"

},

{

test: /\.css$/,

use: [

// MiniCssExtractPlugin.loader的作⽤就是把css-loader处理好的样式资源(js⽂件内),单独提取出来 成为css样式⽂件

MiniCssExtractPlugin.loader,//⽣产环境下使⽤,开发环境还是推荐使⽤style-loader

"css-loader",

],

}],

},

plugins: [

new CleanWebpackPlugin(),

new HtmlWebpackPlugin({

template:"index.html"

}),

new MiniCssExtractPlugin({

filename: "css/built.css",

}),

new OptimizeCssAssetsWebpackPlugin(),

new VueLoaderPlugin(),

]

}

插件都是通过往 Webpack ⽣命周期的钩⼦中挂载任务函数实现的。

class RemoveCommentsPlugin {

apply(compiler) {

compiler.hooks.emit.tap('RemoveCommentsPlugin', compilation => {

// compilation => 可以理解为此次打包的上下⽂

for (const name in compilation.assets) {

if (name.endsWith('.js')) {

const contents = compilation.assets[name].source()

const noComments = contents.replace(/\/\*{2,}\/\s?/g, '')

compilation.assets[name] = {

source: () => noComments,

size: () => noComments.length

}

}

}

})

}

}

1.3.5 Mode

模式(Mode)指示 webpack 使⽤相应模式的配置。

选项描述特点development会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启⽤ NamedChunksPlugin 和 NamedModulesPlugin。能让代码本地调试,运⾏的环境production会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启⽤FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。能让代码优化上线运⾏的环境

⼆、webpack 的使⽤

Webpack 在整个打包的过程中:

通过 Loader 处理特殊类型资源的加载,例如加载样式、图⽚; 通过 Plugin 实现各种⾃动化的构建任务,例如⾃动压缩、⾃动发布。

Webpack CLI 启动打包流程;载⼊ Webpack 核⼼模块,创建 Compiler 对象;使⽤ Compiler 对象开始编译整个项⽬;从⼊⼝⽂件开始,解析模块依赖,形成依赖关系树;递归依赖树,将每个模块交给对应的 Loader 处理;合并 Loader 处理完的结果,将打包结果输出到 dist ⽬录。

先安装 webpack 相关的 npm 包,然后使⽤ webpack-cli 所提供的命令⾏⼯具进⾏打包。

2.1 初始化配置

2.1.1 初始化 package.json

npm init

2.1.2 下载并安装 webpack

npm install webpack webpack-cli -g npm install webpack webpack-cli -D

2.2 编译打包应⽤

2.2.1 创建⽂件

选项 描述 特点 development 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。 启⽤ NamedChunksPlugin 和 NamedModulesPlugin。 能让代码本地调试 运⾏的环境 production 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。 启⽤FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。 能让代码优化上线运⾏的环境

2.2.2 运⾏指令

开发环境指令:webpack src/index.js -o build/built.js --mode=development 功能:webpack 能够编译打包 js 和 json ⽂件,并且能将 es6 的模块化语法转换成浏览器能识别的语法。 ⽣产环境指令:webpack src/index.js -o build/built.js --mode=production 功能:在开发配置功能上多⼀个功能,压缩代码。

2.2.3 结论

webpack 能够编译打包 js 和 json ⽂件。能将 es6 的模块化语法转换成浏览器能识别的语法。能压缩代码。

2.2.4 问题

不能编译打包 css、img等⽂件。不能将 js 的 es6 基本语法转化为 es5 以下语法。

三、webpack 开发、⽣产配置

开发环境配置

/*

开发环境配置:能让代码运行

运行项目指令:

webpack 会将打包结果输出出去

npx webpack-dev-server 只会在内存中编译打包,没有输出

*/

const { resolve } = require('path');

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {

// entry: './src/js/index.js',

entry: resolve(__dirname, './src/js/index.js') ,

//entry: ['./src/js/index.js', './src/index.html'], HMR开启

output: {

filename: 'js/built.js',

path: resolve(__dirname, 'build')

},

module: {

rules: [

// loader的配置

{

// 处理less资源

// 匹配哪些文件

test: /\.less$/, // 匹配哪些文件

// use数组中loader执行顺序:从右到左,从下到上 依次执行

// style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效

// css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串

// less-loader:将less文件编译成css文件 需要下载 less-loader和less

use: ['style-loader', 'css-loader', 'less-loader']

},

{

// 处理css资源

test: /\.css$/,

use: ['style-loader', 'css-loader']

},

{

// 处理图片资源

// 问题:默认处理不了html中img图片

// 处理图片资源

test: /\.(jpg|png|gif)$/,

// 使用一个loader

// 下载 url-loader file-loader

loader: 'url-loader',

options: {

// 图片大小小于8kb,就会被base64处理

// 优点: 减少请求数量(减轻服务器压力)

// 缺点:图片体积会更大(文件请求速度更慢)

limit: 8 * 1024,

// 给图片进行重命名

// [hash:10]取图片的hash的前10位

// [ext]取文件原来扩展名

name: '[hash:10].[ext]',

// 关闭es6模块化

// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs

// 解析时会出问题:[object Module]

// 解决:关闭url-loader的es6模块化,使用commonjs解析

esModule: false,

outputPath: 'imgs'

}

},

{

// 处理html中img资源

// 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)

test: /\.html$/,

loader: 'html-loader'

},

// 打包其他资源(除了html/js/css资源以外的资源)

{

// 处理其他资源

exclude: /\.(html|js|css|less|jpg|png|gif)/,

loader: 'file-loader',

options: {

name: '[hash:10].[ext]',

outputPath: 'font'

}

}

]

},

plugins: [

// plugins的配置

// html-webpack-plugin

// 功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)

// 需求:需要有结构的HTML文件

new HtmlWebpackPlugin({

// 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)

template: './src/index.html'

})

],

mode: 'development',

// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)

// 特点:只会在内存中编译打包,不会有任何输出

// 启动devServer指令为:npx webpack-dev-server

devServer: {

// 运行代码的目录

contentBase: resolve(__dirname, 'build'),

// 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload

watchContentBase: true,

watchOptions: {

// 忽略文件

ignored: /node_modules/

},

// 启动gzip压缩

compress: true,

// 端口号

port: 5000,

// 域名

host: 'localhost',

// 自动打开浏览器

open: true,

// 开启HMR功能

/*

HMR: hot module replacement 热模块替换 / 模块热替换

作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块)

极大提升构建速度

样式文件:可以使用HMR功能:因为style-loader内部实现了~

js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR功能的代码

注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。

html文件: 默认不能使用HMR功能.同时会导致问题:html文件不能热更新了~ (不用做HMR功能)

解决:修改entry入口,将html文件引入

*/

// 当修改了webpack配置,新配置要想生效,必须重新webpack服务

hot: true,

// 不要显示启动服务器日志信息

clientLogLevel: 'none',

// 除了一些基本启动信息以外,其他内容都不要显示

quiet: true,

// 如果出错了,不要全屏提示~

overlay: false,

// 服务器代理 --> 解决开发环境跨域问题

proxy: {

// 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)

'/api': {

target: 'http://localhost:3000',

// 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)

pathRewrite: {

'^/api': ''

}

}

}

},

devtool: 'eval-source-map',

resolve: {

// 配置解析模块路径别名: 优点简写路径 缺点路径没有提示

alias: {

$css: resolve(__dirname, 'src/css')

},

// 配置省略文件路径的后缀名

extensions: ['.js', '.json', '.jsx', '.css'],

// 告诉 webpack 解析模块是去找哪个目录

modules: [resolve(__dirname, '../../node_modules'), 'node_modules']

}

};

生产环境配置

const { resolve } = require("path");

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

const HtmlWebpackPlugin = require("html-webpack-plugin");

// 定义nodejs环境变量:决定使用browserslist的哪个环境

process.env.NODE_ENV = "production";

// 复用loader

const commonCssLoader = [

// 创建style标签,将样式放入

// 'style-loader',

// 这个loader取代style-loader。作用:提取js中的css成单独文件

MiniCssExtractPlugin.loader,

"css-loader",

{

// 还需要在package.json中定义browserslist

/*

css兼容性处理:postcss --> postcss-loader postcss-preset-env

帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式

"browserslist": {

// 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development

"development": [

"last 1 chrome version",

"last 1 firefox version",

"last 1 safari version"

],

// 生产环境:默认是看生产环境

"production": [

">0.2%",

"not dead",

"not op_mini all"

]

}

*/

// 使用loader的默认配置

// 'postcss-loader',

// 修改loader的配置

loader: "postcss-loader",

options: {

ident: "postcss",

plugins: () => [require("postcss-preset-env")()],

},

},

];

module.exports = {

entry: "./src/js/index.js",

output: {

filename: "js/built.js",

path: resolve(__dirname, "build"),

},

module: {

rules: [

{

test: /\.css$/,

use: [...commonCssLoader],

},

{

test: /\.less$/,

use: [...commonCssLoader, "less-loader"],

},

/*

正常来讲,一个文件只能被一个loader处理。

当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:

先执行eslint 在执行babel

*/

{

// 在package.json中eslintConfig --> airbnb

test: /\.js$/,

exclude: /node_modules/,

// 优先执行

enforce: "pre",

loader: "eslint-loader",

options: {

// 自动修复eslint的错误

fix: true,

},

},

/*

js兼容性处理:babel-loader @babel/core

1. 基本js兼容性处理 --> @babel/preset-env

问题:只能转换基本语法,如promise高级语法不能转换

2. 全部js兼容性处理 --> @babel/polyfill

问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~

3. 需要做兼容性处理的就做:按需加载 --> core-js

*/

{

test: /\.js$/,

exclude: /node_modules/,

loader: "babel-loader",

options: {

// 预设:指示babel做怎么样的兼容性处理

presets: [

[

"@babel/preset-env",

{

// 按需加载

useBuiltIns: "usage",

// 指定core-js版本

corejs: { version: 3 },

// 指定兼容性做到哪个版本浏览器

targets: {

chrome: "60",

firefox: "50",

ie: "9",

safari: "10",

edge: "17"

},

},

],

],

cacheDirectory: true //bable 缓存

},

},

{

test: /\.(jpg|png|gif)/,

loader: "url-loader",

options: {

limit: 8 * 1024,

name: "[hash:10].[ext]",

outputPath: "imgs",

esModule: false,

},

},

{

test: /\.html$/,

loader: "html-loader",

},

{

exclude: /\.(js|css|less|html|jpg|png|gif)/,

loader: "file-loader",

options: {

outputPath: "font",

},

},

],

},

plugins: [

// 对输出的css文件进行重命名

new MiniCssExtractPlugin({

filename: "css/built.css",

}),

// 压缩css

new OptimizeCssAssetsWebpackPlugin(),

// 压缩html代码

new HtmlWebpackPlugin({

template: "./src/index.html",

minify: {

// 移除空格

collapseWhitespace: true,

// 移除注释

removeComments: true,

},

}),

],

// 生产环境下会自动压缩js代码

mode: "production",

externals: {

// 拒绝jQuery被打包进来

jquery: 'jQuery'

}

};

四、webpack 性能优化

4.1 开发环境性能优化

优化打包构建速度

HMR 优化代码调试

source-map : ⼀种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

a.source-map:外部 产⽣⼀个单独的source-map⽂件,功能最完全,但会减慢打包速度b. inline-source-map:内联 只⽣成⼀个内联source-map 错误代码准确信息 和 源代码的错误位置c. hidden-source-map:外部 错误代码错误原因,但是没有错误位置 不能追踪源代码错误,只能提示到构建后代码的错误位置d.eval-source-map:内联 使⽤eval打包源⽂件模块,直接在源⽂件中写⼊⼲净完整的source-map,不影响构建速度,但影响执⾏速度和安 全,建议开发环境中使⽤,⽣产阶段不要使⽤e.nosources-source-map:外部 错误代码准确信息, 但是没有任何源代码信息f.cheap-source-map:外部 错误代码准确信息 和 源代码的错误位置,只能精确的⾏g.cheap-module-source-map:外部 错误代码准确信息 和 源代码的错误位置 module会将loader的source map加⼊

内联 和 外部的区别:1. 外部⽣成了⽂件,内联没有 2. 内联构建速度更快

开发环境推荐使⽤:

1.eval :每个模块使⽤eval()和//@ sourceURL执⾏。这是⾮常快。主要缺点是,它没有正确显示⾏号,因为它被映射到转换代码⽽不是原始代码(没有来⾃加载器的源映射)。2.eval-source-map:每个模块使⽤eval()执⾏,⽽SourceMap作为DataUrl添加到eval()中。最初它是缓慢的,但是 它提供快速的重建速度和产⽣真实的⽂件。⾏号被正确映射,因为它被映射到原始代码。它产⽣了最优质的开发资源。3.cheap-eval-source-map:与eval-source-map类似,每个模块都使⽤eval()执⾏。它没有列映射,它只映射⾏ 号。它忽略了来⾃加载器的源代码,并且只显示与eval devtool相似的经过转换的代码。4.cheap-module-eval-source-map:类似于cheap-eval-source-map,在本例中,来⾃加载器的源映射被处理以获 得更好的结果。然⽽,加载器源映射被简化为每⼀⾏的单个映射。

⽣产环境推荐使⽤:

1.(none) :(省略devtool选项)-不触发SourceMap。这是⼀个很好的选择。2.source-map:⼀个完整的SourceMap是作为⼀个单独的⽂件。它为bundle 添加了引⽤注释,因此开发⼯具知道在哪⾥找到它。3.hidden-source-map:与source-map相同,但不向bundle 添加引⽤注释。如果您只希望SourceMaps从错误报告 中映射错误堆栈跟踪,但不想为浏览器开发⼯具暴露您的SourceMap,可以使⽤此选项。4.nosources-source-map:⼀个SourceMap是在没有源代码的情况下创建的。它可以⽤于在客户机上映射堆栈跟 踪,⽽不暴露所有源代码。您可以将源映射⽂件部署到webserver。

webpack devtool: https://webpack.docschina.org/configuration/devtool/

4.2 ⽣产环境性能优化

优化打包构建速度

oneOf --每个不同类型的⽂件在 loader 转换时,都会被命中,遍历 module 中 rules 中所有 loader.

使⽤ oneOf 根据⽂件类型加载对应的 loader,只要能匹配⼀个即可退出,对于同⼀类型⽂件,⽐如处理 js,如果需要多个 loader,可以单独抽离 js 处理,确保 oneOf ⾥⾯⼀个⽂件类型对应⼀个 loader可以配置 enforce: ‘pre’,指定优先执⾏ babel 缓存: cacheDirectory: true --> 让第⼆次打包构建速度更快

hash: 每次 wepack 构建时会⽣成⼀个唯⼀的 hash 值。 问题: 因为 js 和 css 同时使⽤⼀个 hash 值。–> 如果重新打包,会导致所有缓存失效。(可能我却只改动⼀个⽂件)chunkhash:根据 chunk ⽣成的 hash 值。如果打包来源于同⼀个 chunk,那么 hash 值就⼀样 问题: js 和 css 的 hash 值还是⼀样的–> 因为 css 是在 js 中被引⼊的,所以同属于⼀个 chunkcontenthash: 根据⽂件的内容⽣成 hash 值。不同⽂件 hash 值⼀定不⼀样–> 让代码上线运⾏缓存更好使⽤ 多进程打包externalsdll 优化代码运⾏的性能

缓存(hash-chunkhash-contenthash)tree shakingcode split懒加载/预加载pwa

好文推荐

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。