webpack知识点总结(基础应用篇)

一、为什么需要webpack

1.为什么使用webpack

 ①传统的书写方式,加载太多脚本会导致网络瓶颈,如不小心改变JavaScript文件加载顺序,项目会崩溃,还会导致作用域问题、js文件太大无法做到按需加载、可读性和可维护性太低的问题。

②当今JavaScript、css的语法规范不断更新,但是浏览器的兼容性却不能同步的更新,开发者可以通过 webpack 预处理器进行编译,自由的使用 JS、CSS 等语言的新语法。

③Vue 脚手架vue-cli、React 脚手架create-react-app、Taro 脚手架taro-cli都是使用webpack,开发者掌握 webpack后,可以自由配置脚手架,根据项目需要,去调整 webpack 配置,以提高项目性能。

④拥有依赖管理、动态打包、代码分离、按需加载、代码压缩、静态资源压缩、缓存等配置;扩展性强,插件机制完善,开发者可自定义插件、loader;webpack 社区庞大,更新速度快,轮子丰富;

1.由于浏览器解析html的顺序是从上至下,引入第三方库时便会存在先后顺序问题;作用域是由于存在多个JS文件时,window下有可能挂载多个相同或不同变量

→解决方案:使用立即调用函数表达式 IIFE 来创建独立作用域

2.js文件过于庞大时无法做到按需加载,如引用第三方工具库lodash等

→解决:

①(依赖nodeJS实现)使用commonJs的module.exports来抛出模块代码,使用require来引入模块

②(不依赖nodeJS实现)可以使用browserify、requireJS等打包工具实现

  • 在没有各个 webpack 搭建的脚手架(create-react-app、vue-cli 等等)之前,我们通过在 HTML5 文件里引入一个个 Javascript 文件来进行开发,这就可能导致并行请求数量过多、存在重复代码等问题。
  • 而通过 webpack,我们可以使用 import、require 来进行模块化开发。
  • 在 webpack 中一切皆模块,js、css、图片、字体都是模块,而且支持静态解析、按需打包、动态加载、代码分离等功能,帮助我们优化代码,提升性能。

2.什么是webpack?

Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。

  • Webpack是一个模块打包器。
  • 在Webpack中会将前端的所有资源文件(js/json/css/img/less/...)都作为模块处理。
  • 它将根据模块的依赖关系进行分析,生成对应的资源

3.五个核心概念:

  1. 【入口(entry)】:指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
  2. 【输出(output)】:在哪里输出文件,以及如何命名这些文件。
  3. 【Loader】:处理那些非 JavaScript 文件(webpack 自身只能解析 JavaScript和json)。
  4. 【插件(plugins)】执行范围更广的任务,从打包到优化都可以实现。
  5. 【模式(mode)】,有生产模式production和开发模式development
  • 对loader的理解:webpack 本身只能处理JS、JSON模块,如果要加载其他类型的文件(模块),就需要使用对应的loader 。它本身是一个函数,接受源文件作为参数,返回转换的结果。loader 一般以 xxx-loader 的方式命名,xxx 代表了这个 loader 要做的转换功能,比如 css-loader。
  • 对plugins的理解:插件可以完成一些loader不能完成的功能。

4.配置文件

  • webpack.config.js : 用于存储webpack配置信息。

二、webpack与竞品

Webpack :为处理资源管理和分割代码而生,可以包含任何类型的文件。灵活,插件 多。

Parcel :是 0 配置工具, 用户一般无需再做其他配置即可开箱即用。

Rollup:用标准化的格式(es6)来写代码,通过减少死代码尽可能地缩小包体积。 一般只用来打包JS。 

构建一个简单的应用并让它快速运行起来?使用 Parcel。

构建一个类库只需要导入很少第三方库?使用 Rollup。

构建一个复杂的应用,需要集成很多第三方库?需要代码分拆,使用静态资源文件, 还有 CommonJS 依赖?使用 webpack。

 Vite 将成 为 Vue 的现代标配。甚至最近新推出的 Petite Vue 从开发、编译、发布、Demo几 乎全都是使用 Vite 完成。Webpack、Vite 作为前端热门的工程化构建工具,它们都有各自的适用场景。

 三、安装webpack

1.本地安转

npm install --save-dev webpack# 或指定版本
npm install --save-dev webpack@<version>

如果你使用 webpack v4+ 版本,并且想要在命令行中调用 webpack,你还需要安装 CLI。

npm install --save-dev webpack-cli

对于大多数项目,我们建议本地安装。这可以在引入重大更新(breaking change)版本时,更容易分别升级项目。 通常会通过运行一个或多个 npm scripts 以在本地 node_modules 目录中查找安装的 webpack, 来运行 webpack:

"scripts": {"build": "webpack --config webpack.config.js"}

2.全局安装

npm install --global webpack

不推荐 全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中, 可能会导致构建失败。

  • 安装node.js https://nodejs.org/zh-cn/ 最新LTS版本
  • 验证node版本 node -v
  • 验证npm版本 npm -v
  • (可选)执行 npm i webpack webpack -cli --global (全局)安装webapck
  • 在当前文件目录下执行 webpack -v 验证版本
  • npm init -y 初始化package配置文件
  • npm install webpack webpack-cli --save-dev 本地安装webpack及webpack-cli

四、运行webpack

  • 在终端中输入 webpack 回车会生成dist文件夹即打包后的文件 (使用全局webpack)
  • webpack --status detailed 查看详细打包信息(使用全局webpack
  • npx webpack 使用当前目录webpack

进入项目目录,运行webpack,执行指令:

npx webpack

生成了一个main.js文件

五、自定义webpack配置

实际上, webpack-cli 给我们提供了丰富的终端命令行指令,可以通过npx webpack --help 查看帮助信息。

  • npx webpack --entry ./src/index.js --mode production 设置入口文件

可是命令行不方便也不直观,而且还不利于保存配置的内容,可以采取配置config的方式。因此,webpack 还给我们提供了通过配置文件,来自定义配置参数的能力。

  • 可以在当前目录下新建webpack.config.js文件,用commonJs写法抛出配置模块:
const { resolve } = require('path'); //node内置核心模块,用来设置路径。module.exports = {//入口是指依赖关系图的开始,从入口开始寻找依赖,打包构建。webpack 允许一个或多个入口配置。entry: './src/js/app.js', // 入口文件配置(精简写法)/*完整写法:entry:{main:'./src/js/app.js'}*///输出则是用于配置 webpack 构建打包的出口,如打包的位置,打包的文件名等等。output: { //输出配置clean: true, //打包前清理 dist 文件夹,在每次构建前清理 /dist文件夹,这样只会生成用到的文件。filename: 'bundle.js',//输出文件名path: resolve(__dirname, './dist')//输出文件路径(绝对路径),require的path为nodeJS自带,__dirname可直接匹配当前目录},mode: 'development'   //开发环境(二选一) webpack编译模式,区分生产测试环境 //mode: 'production'   //生产环境(二选一)// 文件监视改动,自动产出bundle.jsdevtool: 'inline-source-map'//精准定位代码行数,便于查看。在开发模式下追踪代码watch: true //观察模式,自动检测变化,但需要手动刷新浏览器,如果其中一个文件被更新,代码将被重新编译,所以不必再去手动运行整个构建。
};

使用 webpack-dev-server

webpack-dev-server支持文件打包后的本地代码实时更新,提高webpack开发效率。提供了一个基本的 web server,并且具有 live reloading(实时重新加载) 功能。可以自动检测文件变化,从而重新编译,帮助我们自动实现浏览器的刷新。

先安装:

npm install --save-dev webpack-dev-server

也可以通过npx webpack命令后缀添加--watch 实现编译时自动检测文件变化(需要手动刷新浏览器)

本地安装: npm install webpack-dev-server -D

修改配置文件,告知 dev server,从什么位置查找文件:

module.exports={...devServer:{static:'./dist'},
}

以上配置告知 webpack-dev-server,将 dist 目录下的文件作为 web 服务的根目录。

执行命令:

npx webpack serve --open
  • 执行 npx webpack --dev-server --watch
  • 也可以 npx webpack serve

webpack-dev-server 在编译之后不会写入到任何输出文件。而是将 bundle 文件保留在内存中,然后将它们 serve 到 server 中,就好像它们是挂载在 server 根路径上的真实文件一样。

六、自动引入资源

1.什么是插件?

随着应用程 序增长,如果继续手动管理,就会变得困难起来。然而,webpack在打包流程中产生的编译过程,可以借助插件实现某些功能,通过一些插件可以使这个过程更容易管控。

插件是 webpack 的核心功能。插件可以用于执行一些特定的任务,包括:打包优化,资源管理,注入环境变量等。Webpack自身也是构建于你在webpack 配置中用到的相同的插件系统之上。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。 多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而 多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。

2.使用html-webpack-plugin

本地安装:

npm install html-webpack-plugin -D

config中添加配置:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports={entry:'./src/index.js',output:{// 打包前清理 dist 文件夹clean: true,filename:'bundle.js',path:path.resolve(__dirname,'./dist')},mode:'development',devtool: 'inline-source-map' ,//插件配置集合plugins:[new HtmlWebpackPlugin()],
}

new HtmlWebpackPlugin() 中也可以添加配置项

    plugins:[...new HtmlWebpackPlugin({template:'./index.html',//指向的htmlfilename:'app.html',//被打包后的html文件名inject:'body'// js打包后的生成位置}),]

七、引入资源

1.Resource-发送单独文件并导出Url

修改webpack.config.js配置: 

const path = require('path')const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = {//...// 配置资源文件module: {rules: [{test: /\.png/,type: 'asset/resource'}]},//...
}

 在module中设置文件类型及资源类型,output端中增加打包后的资源文件夹配置:

    output:{filename:'bundle.js',path:path.resolve(__dirname,'./dist'),clean:true,assetModuleFilename:'images/[contenthash][ext]',},

2.inline-导出资源的Data Url

module:{rules:[...{test:/\.svg$/,type:'asset/inline'}]
}

 实际展示出的文件的url为base64格式

3.source-导出资源的源代码

module:{rules:[...{test:/\.txt$/,type:'asset/source'}]
}

4.asset-通用资源类型-自动选择data url或源文件

module:{rules:[...{test:/\.jpg$/,type:'asset',parser:{dataUrlCondition:{maxSize:4 * 1024 * 1024 //当图片大小大于4M时生成资源文件,否则为base64 url}}}]
}

可以通过配置临界值实现自动切换资源格式,更加灵活可控(默认大小为8kb)

八、管理资源

除了以上四个资源模块,我们还可以通过webpack-loader引入其他类型的文件。webpack只能解析JS、JSON文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,通过loader可以实现在js上加载css等其他文件。

在 webpack 的配置中,loader 有两个属性:

  • 1. test 属性,识别出哪些文件会被转换。
  • 2. use 属性,定义出在进行转换时,应该使用哪个 loader。
 const path = require('path');module.exports = {output: {filename: 'my-first-webpack.bundle.js',},module: {rules: [{ test: /\.txt$/, use: 'raw-loader' }],},};
//以上配置中,对一个单独的 module 对象定义了 rules 属性,里面包含两个必须属性:
//test 和 use。这告诉 webpack 编译器(compiler) 如下信息:
//“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为'.txt' 的路径」时,
//在你对它打包之前,先 use(使用) raw-loader 转换一下。

1.加载CSS

  • 本地安装css-loader及style-loader npm install css-loader -D
  • 并在规则中添加css
module:{rules:[...{test:/\.css$/,use:['style-loader','css-loader']}]
}

应保证 loader 的先后顺序: 'style loader' 在前,而 'css loader' 在后。如果 不遵守此约定,webpack 可能会抛出错误。 

2.抽离和压缩CSS

在多数情况下,我们也可以进行压缩CSS,以便在生产环境中节省加载时间,同时还可以将CSS文件抽离成一个单独的文件。

抽离

实现这个功能,需要mini-css-extract-plugin这个插件来帮忙,本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

  • 本地安装mini-css-extract-plugin : npm install mini-css-extract-plugin -D
  • 基于webpack5构建,需要webpack5环境下才能正常使用
  • 和style-loader不同,MiniCssExtractPlugin会生成link标签从而引入外部css
<!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>Webpack5学习指南</title><link href="main.css" rel="stylesheet"></head><body><script defer src="bundle.js"></script></body></html>

将 loader 与 plugin 添加到你的 webpack 配置文件中。通过require引入后在plugins里添加引用,同时在原有css规则中替换掉style-loader,npx webpack打包后生效。

plugins:[new HtmlWebpackPlugin({template:'./index.html',filename:'app.html',inject:'body'}),new MiniCssExtractPlugin()
]
module:{rules:[...{test:/\.css$/,use:[MiniCssExtractPlugin.loader,'css-loader']}]
}

在plugins里调用MiniCssExtractPlugin时也可以添加filename来自定义生成目录及文件名。

contenthash会随机生成字符串的文件名:

    plugins:[...new MiniCssExtractPlugin({filename:'styles/[contenthash].css'}),],

压缩

  • 本地安装css-minimizer-webpack-plugin: npm install css-minimizer-webpack-plugin -D
  • 和其他插件不同,需在optimization中添加配置,并且mode要切换为production
//优化配置
optimization:{minimizer:[new CssMinimizerPlugin(),],
}
//生产模式
mode:'production'

3.加载images图像

假如,现在我们正在下载 CSS,但是像 background 和 icon 这样的图像,要如何处理呢?在 webpack 5 中,可以使用内置的 Asset Modules,可以将这些内容混入我们的系统中,在 css文件里也可以直接引用文件,修改style.css 和入口 index.js,依赖于资源模块

module:{rules:[...{test:/\.png$/,type:'asset/resource',generator:{filename:'images/[contenthash][ext]'}}]
}

打包后:

import './style.css'

4.加载fonts字体

?使用 Asset Modules 可以接收并加载任 何文件,然后将其输出到构建目录。这就是说,我们可以将它们用于任何类型的文 件,也包括字体。

module:{rules:[...{test:/\.(woff|woff2|eot|ttf|otf)$/,type:'asset/resource'}]
}

在css中引用并创建字体图标库

@font-face {font-family: 'iconfont';src: url('../icon/iconfont.ttf') format('truetype');
}

5.加载数据

可以加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML。类似于 NodeJS,JSON 支持实际上是内置的,也就是说 import Data from loader 和 './data.json' 默认将正常运行。

  • 根据数据格式安装不同的loader模块,比如要导入 CSV、TSV 和 XML,可以使用csv-loader和xml-loader。
  • 本地安装 csv-loader xml-loader : npm install csv-loader xml-loader -D
  • 在项目中引入csv、xml等数据格式时会自动转化为对象、数组等JS数据格式
module:{rules:[...{test:/\.(csv|tsv)$/,use:'csv-loader'},{test:/\.xml$/,use:'xml-loader'}]
}
//现在,你可以 import 这四种类型的数据(JSON, CSV, TSV, XML)中的任何一种,
//所导入的 Data 变量,将包含可直接使用的已解析 JSON

6.自定义JSON模块parser

通过使用自定义 parser 替代特定的webpack loader,可以将任何toml、yaml或json5文件作为JSON导入。

本地安装  toml yaml json5 :npm install toml yaml json5 -D

引入模块:

const toml = require('toml')
const yaml = require('yaml')
const json5 = require('json5')

添加规则:

module:{rules:[...{test:/\.xml$/,use:'xml-loader'},{test:/\.toml$/,type:'json',parser:{parse:toml.parse}},{test:/\.yaml$/,type:'json',parser:{parse:yaml.parse}},{test:/\.json5$/,type:'json',parser:{parse:json5.parse}}]
}

7.使用babel-loader

webpack 自身可以自动加载JS文件,就像加载JSON文件一样,无需任何 loader。但加载的JS文件会原样输出,即使你的JS文件里包含ES6+的代码,也不会做任何转化。这时我们就需要Babel来帮忙。Babel 是一个 JavaScript 编译器,可以将 ES6+转化成ES5,将js代码转化以提供兼容度支持。在Webpack里使用Babel,需要使用babel-loader。

  • babel-loader: 在webpack里应用 babel 解析ES6的桥梁
  • @babel/core: babel核心模块
  • @babel/preset-env: babel预设,一组 babel 插件的集合

本地安装: babel-loader @babel/core @babel/preset-env : npm install babel-loader @babel/core @babel/preset-env -D

在 webpack 配置中,添加babel-loader到module中:

module:{rules:[...{test:/\.js$/,exclude:/node_modules/,use:{loader: 'babel-loader',options:{presets:['@babel/preset-env']}}}]
}

注意:

  • 需在exclude中排除node_modules包
  • 如需兼容async/await语法则还需要添加regeneratorRuntime模块。regeneratorRuntime是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法。
  • npm install --save @babel/runtime【这个包中包含了regeneratorRuntime,运行时需要】
  • npm install --save-dev @babel/plugin-transform-runtime【这个插件会在需要regeneratorRuntime的地方自动require导包,编译时需要】
module:{rules:[...{test:/\.js$/,exclude:/node_modules/,use:{loader: 'babel-loader',options:{presets:['@babel/preset-env'],plugins:[['@babel/plugin-transform-runtime']]}}}]
}

九、代码分离

代码分离是 webpack 中最引人注目的特性之一。此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。项目中若存在多个入口文件时,则需要代码分离;若存在多个模块共用的代码时,也需要分离代码来防止重复打包。

代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。常用的代码分离方法有三种:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 防止重复:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离 chunk。
  • 动态导入:通过模块的内联函数调用来分离代码。

1.入口起点

module.exports = {entry: {//将其他包命名在entry中index: './src/index.js',another: './src/another-module.js',},output: {//并在output输出端中直接配置[name]对应entry中的keyfilename: '[name].bundle.js'//...},//...}

执行npx webpack后便会提示相应包名被分别打包且都被引入

存在一些隐患:

  • 如果入口 chunk 之间包含一些重复的模块,那些重复模块都会被引入到各个 bundle 中。
  • 这种方法不够灵活,并且不能动态地将核心应用程序逻辑中的代码拆分出来。

2.防止重复

Entry dependencies

入口依赖,当图中两个模块共有lodash时,会抽离出来并取名为lodash。配置 dependOn option 选项,这样可以在多个 chunk 之间共享模块:

    entry:{index:{import:'./src/index.js',dependOn:'shared'},another:{import:'./src/another-module.js',dependOn:'shared'},shared:'lodash'index:'./src/index.js',another:'./src/another-module.js'},

打包后多出的shared.budle.js即为定义中的模块,此时lodash是共用的,做到了模块的去重和分离

SplitChunksPlugin

可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。

配置时依旧可以采用独立命名

    entry:{index:'./src/index.js',another:'./src/another-module.js'},

在 optimization 优化配置项中添加 splitChunks

    optimization:{...splitChunks:{chunks:'all'}},

执行之后可以发现,使用 optimization.splitChunks 配置选项之后,index.bundle.js 和 another.bundle.js 中已经移除了重复的依赖模块。注意,插件将 lodash分离到单独的chunk,并且将其从main bundle 中移除,减轻了大小。

3.动态导入

当涉及到动态代码拆分时,webpack 提供了两个类似的技术。

  • 第一种,也是推荐选择的方式是,使用符合ECMAScript提案的import()语法来实现动态导入,且不影响其他模块抽离方式。

async-module.js 假设为功能模块:

// async-module.js
function getComponent(){return import('lodash').then(({default:_})=>{const element = document.createElement('div')element.innerHTML = _.join(['hello','webpack'],' ')return element})
}getComponent().then((element)=>{document.body.appendChild(element)
})

在入口文件中导入:

import './async-module'
  • 第二种,则是webpack的遗留功能,使用 webpack 特定的 require.ensure。

4.懒加载

懒加载或按需加载,是一种很好的优化网页或应用的方式。这种方式实际上是先把代码在一些逻辑断点处分离开,然后在一些代码块中完成某些操作后,立即引用或即将引用另外一些新的代码块。这样加快了应用的初始加载速度,减轻了它的总体体积,因为某些代码块可能永远不会被加载。

依旧通过import直接引入模块,区别在于:何时调用何时加载模块

const button = document.createElement('button')button.textContent = '点击执行加法运算'button.addEventListener('click', () => {import(/* webpackChunkName: 'math' */ './math.js').then(({ add 
}) => {console.log(add(4, 5))})
})document.body.appendChild(button)

加上注释 webpackChunkName:'模块名' 后,可以定义打包后的模块名

import(/* webpackChunkName:'math' */'./math.js')

第一次加载完页面, math.bundle.js不会加载,当点击按钮后,才加载 math.bundle.js文件。

5.预获取/预加载模块

在声明import时,使用下面这些内置指令,可以让webpack输出“resource hint(资源提示)”,来告知浏览器:

  • prefetch(预获取):将来某些导航下可能需要的资源 ,即在浏览器网络空闲时再获取资源
  • preload(预加载):当前导航下可能需要资源,和懒加载效果类似

prefetch

依旧在import引入时的注释中添加

const button = document.createElement('button')
button.textContent = '点击执行加法运算'
button.addEventListener('click',()=>{import(/* webpackChunkName:'math',webpackPrefetch:true */'./math.js').then(({add})=>{console.log(add(4,5));})
})
document.body.appendChild(button)

加上注释 webpackPrefetch: true 后,可以告诉 webpack 执行预获取。会生成<link rel="prefetch" href="main.js">并追加到页面头部,指示着浏览器在闲置时间预取 math.js 文件。

我们发现,在还没有点击按钮时,math.bundle.js就已经下载下来了。同时,在 app.html可以看到,点击按钮,会立即调用已经下载好的 math.bundle.js文件中的 add 方法。

preload

  • 与 prefetch 指令相比,preload 指令有许多不同之处:
  • preload chunk 会在父 chunk 加载时,以并行方式开始加载。prefetch chunk 会在父 chunk 加载结束后开始加载。
  • preload chunk 具有中等优先级,并立即下载。prefetch chunk 在浏览器闲置时下载。
  • preload chunk 会在父 chunk 中立即请求,用于当下时刻。prefetch chunk 会用于未来的某个时刻。
  • 浏览器支持程度不同。

十、缓存

打包后的dist文件部署到服务器以后便能被浏览器客户端所访问,因浏览器的解析特性会优先选择缓存资源,我们要确保文件发生更新时浏览器能识别到,所以需要对输出文件的文件名做处理。

1.输出文件的文件名

我们可以通过替换 output.filename 中的 substitutions 设置,来定义输出文件的名称。webpack提供了一种使用 substitution (可替换模板字符串)的方式,通过带括号字符串来模板化文件名,其中,[contenthash] substitution 将根据资源内容创建出唯一的hash。当资源内容发生变化时, [contenthash] 也会发生变化。

module.exports = {output: {filename: '[name].[contenthash].js',},
};

2.缓存第三方库

将第三方库 (library)  (例如 lodash)  提取到单独的 vendor chunk 文件中,是比较推荐的做法,因为第三方库文件很少像本地源码那样频繁修改,所以我们可以利用client的长效缓存机制,命中缓存来消除请求,并减少向server 获取资源,同时保证client和server的代码一致。

在 optimization.splitChunks 添加cacheGroups 参数并构建:

	optimization:{...splitChunks:{...cacheGroups:{vendor:{test:/[\\/]node_modules[\\/]/,name:'vendors',chunks:'all'}},}}

3.将js文件放到一个文件夹中

目前,全部 js 文件都在 dist文件夹根目录下,我们尝试把它们放到一个文件夹中, 这个其实也简单,在输出配置中修改 filename,即output.filename加上scripts前缀即可汇总js文件至指定文件夹下生成。

output:{filename:'scripts/[name].[contenthash].js',...
}

十一、拆分开发环境和生产环境配置

1.公共路径

publicPath 配置选项在各种场景中都非常有用,我们可以通过它来指定应用程序中所有资源的基础路径。

output:{filename:'scripts/[name].[contenthash].js',path:path.resolve(__dirname,'./dist'),clean:true,assetModuleFilename:'images/[contenthash][ext]',publicPath:'http://localhost:8080/'
},
  • 基于环境设置

在开发环境中,我们通常有一个assets/ 文件夹,它与索引页面位于同一级 别。这没太大问题,但是,如果我们将所有静态资源托管至 CDN,然后想在生产环境中使用呢? 想要解决这个问题,可以直接使用一个 environment variable(环境变量)。假设我们有一个变量 ASSET_PATH:

import webpack from 'webpack';// 尝试使用环境变量,否则使用根路径
const ASSET_PATH = process.env.ASSET_PATH || '/';
export default {output: {publicPath: ASSET_PATH,},plugins: [// 这可以帮助我们在代码中安全地使用环境变量new webpack.DefinePlugin({'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),}),],
};
  • Automatic publicPath

有可能你事先不知道 publicPath 是什么,webpack 会自动根据 import.meta.url、 document.currentScript、 script.src 或者 self.location 变量设置 publicPath。你需要做的是将 output.publicPath 设为 ' auto':

module.exports = {output: {publicPath: 'auto',},
};

注意:在某些情况下不支持 document.currentScript,例如:IE 浏览器,不得不引入一个 polyfill,例如 currentScript Polyfill。

2.环境变量

想要消除 webpack.config.js 在开发环境和生产环境之间的差异,需要环境变量(environment variable)。webpack命令行环境配置的 --env 参数,可以允许传入任意数量的环境变量。而webpack.config.js 中可以访问到这些环境变量。例如,--env production 或--env goal=local。

  • npx webpack --env production 可以通过命令传入变量区分环境

对于我们的 webpack 配置,有一个必须要修改之处。通常,module.exports 指向配置对象。要使用 env 变量,你必须将 module.exports(抛出对象)转换为函数后即可动态传参

//...module.exports = (env) => {return {//...// 根据命令行参数 env 来设置不同环境的 modemode: env.production ? 'production' : 'development',//...}
}

3.拆分配置文件

生产环境和开发环境使用的是一个配置文件,我们需要将这两个文件单独放到不同的配置文件中。如 webpack.config.dev.js(开发环境配置)和 webpack.config.prod.js(生产环境配置)。在项目根目录下创建一个配置文件夹config 来存放他们。

  • 开发环境:执行 npx webpack serve -c config文件路径
  • 生产环境:执行 npx webpack -c config文件路径

4.npm命令

每次打包或启动服务时,都需要在命令行里输入一长串的命令。我们将父目录的 package.json、 node_modules 与 package-lock.json拷贝到当前目录下,

可以在package.json中配置命令来方便使用,配置 npm 脚本来简化命令行的输入。

"scripts": {"start": "webpack serve -c ./config/webpack.config.js --env development","build": "webpack -c ./config/webpack.config.js --env production"
},
  • 开发环境运行脚本:npm run start
  • 生产环境运行脚本:npm run build

关闭生产环境打包的文件过大警告提示:

performance:{hints:false
}

5.提取公共配置

拆分出的配置文件存在大量重复配置代码时,可以单独创建一个公共配置文件,手动的将这些重复的代码单独提取到一个文件里。创建 webpack.config.common.js,配置公共的内容。

6.合并配置文件

配置文件拆分好后,我们又需要保证配置合并没用的问题,这时候就需要webpack-merge这个工具。

  • 安装 npm install webpack-merge -D
  • 创建新的config文件用以合并
const {merge} = require('webpack-merge')const commonConfig = require('./webpack.config.common')
const productionConfig = require('./webpack.config.prod')
const developmentConfig = require('./webpack.config.dev')module.exports=((env)=>{switch(true){case env.development:return merge(commonConfig,developmentConfig)case env.production:return merge(commonConfig,productionConfig)default:return new Error('No matching configuration was found')}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/233451.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue+ElementUI前端添加展开收起搜索框按钮

1、搜索框添加判断 v-if"advanced" <el-form-item label"创建日期" v-if"advanced"><el-date-pickerv-model"daterangeLedat"size"small"style"width: 240px"value-format"yyyy-MM-dd"type&q…

深入了解常见的应用层网络协议

目录 1. HTTP协议 1.1. 工作原理 1.2. 应用场景 1.3. 安全性考虑 2. SMTP协议 2.1. 工作原理 2.2. 应用场景 2.3. 安全性考虑 3. FTP协议 3.1. 工作原理 3.2. 应用场景 3.3. 安全性考虑 4. DNS协议 4.1. 工作原理 4.2. 应用场景 4.3. 安全性考虑 5. 安全性考虑…

scrapy的入门和使用

scrapy的入门使用 学习目标&#xff1a; 掌握 scrapy的安装应用 创建scrapy的项目应用 创建scrapy爬虫应用 运行scrapy爬虫应用 scrapy定位以及提取数据或属性值的方法掌握 response响应对象的常用属性 1 安装scrapy 命令:     sudo apt-get install scrapy 或者&#x…

持续集成交付CICD:K8S 自动化完成前端项目应用发布与回滚

目录 一、实验 1.环境 2.GitLab新建项目存放K8S部署文件 3.Jenkins手动测试前端项目CD 流水线代码&#xff08;下载部署文件&#xff09; 4. 将K8S master节点配置为jenkins从节点 5.K8S 手动回滚前端项目版本 6.Jenkins手动测试前端项目CD 流水线代码&#xff08;发布应…

C++学习笔记(十六)

一、多态 1. 多态的基本概念 多态是C面向对象三大特性之一 多态分为两类 1. 静态多态&#xff1a;函数重载 和 运算符重载属于静态多态&#xff0c;复用函数名 2. 动态多态&#xff1a;派生类和虚函数实现运行时多态 静态多态和动态多态区别&#xff1a; 1. 静态多态的函…

useConsole的封装,vue,react,htmlscript标签,通用

之前用了接近hack的方式实现了console的封装&#xff0c;目标是获取console.log函数的执行&#xff08;调用栈所在位置&#xff09;所在的代码行数。 例如以下代码&#xff0c;执行window.mylog(1)时候&#xff0c;console.log实际是在匿名的箭头函数()>{//这里执行的} con…

【IDEA】Intellij IDEA相关配置

IDEA 全称 IntelliJ IDEA&#xff0c;是java编程语言的集成开发环境。IntelliJ在业界被公认为最好的Java开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等方面的功能可以说是超…

SpringCloud源码探析(十二)-基于SpringBoot开发自定义中间件

1.概述 中间件是一种介于操作系统和应用软件之间&#xff0c;为应用软件提供服务功能的软件&#xff0c;按功能划分有消息中间件&#xff08;Kafka、RocketMQ&#xff09;、通信中间件&#xff08;RPC通信中间件&#xff0c;dubbo等&#xff09;&#xff0c;应用服务器等。中间…

Java实现一个在windows环境下的文件搜索引擎

以下是一个简单的Java实现的Windows文件搜索引擎的示例代码&#xff1a; import java.io.File; import java.util.ArrayList; import java.util.List;public class FileSearchEngine {public static void main(String[] args) {String searchDirectory "C:/"; // …

tensorflow入门 自定义模型

前面说了自定义的层&#xff0c;接下来自定义模型&#xff0c;我们以下图为例子 这个模型没啥意义&#xff0c;单纯是为了写代码实现这个模型 首先呢&#xff0c;我们看有几个部分&#xff0c;dense不需要我们实现了&#xff0c;我们就实现Res&#xff0c;为了实现那个*3,我们…

WPF——样式和控件模板、数据绑定与校验转换

样式和控件模板 合并资源字典 Style简单样式的定义和使用 ControlTemplate控件模板的定义和使用 定义 使用 Trigger触发器 数据绑定与校验转换 数据绑定的设置 代码层实现绑定

TransXNet实战:使用 TransXNet实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度&#xff0c;DP多卡&#xff0c;EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

监控k8s controller和scheduler,创建serviceMonitor以及Rules

目录 一、修改kube-controller和kube-schduler的yaml文件 二、创建service、endpoint、serviceMonitor 三、Prometheus验证 四、创建PrometheusRule资源 五、Prometheus验证 直接上干货 一、修改kube-controller和kube-schduler的yaml文件 注意&#xff1a;修改时要一个节…

HTML CSS 进度条

1 原生HTML标签 <meter>&#xff1a;显示已知范围的标量值或者分数值<progress>&#xff1a;显示一项任务的完成进度&#xff0c;通常情况下&#xff0c;该元素都显示为一个进度条 1.1 <meter> <html><head><style>meter{width:200px;}…

微软官宣放出一个「小模型」,仅2.7B参数,击败Llama2和Gemini Nano 2

就在前一阵谷歌深夜炸弹直接对标 GPT-4 放出 Gemini 之后&#xff0c;微软这两天也紧锣密鼓进行了一系列动作。尽管时间日趋圣诞假期&#xff0c;但是两家巨头硬碰硬的军备竞赛丝毫没有停止的意思。 就在昨日&#xff0c;微软官宣放出一个“小模型” Phi-2&#xff0c;这个 Ph…

学习k8s

学习k8s 我为什么要用k8s 和其他部署方式的区别是什么? 传统部署方式 java --> package --> 放到服务器上 --> Tomcat 如果是同时进行写操作,会存在并发问题. 用户 --网络带宽–> 服务器 -->服务 同一个服务器上,多个服务: 网络资源的占用 内存的占用 cpu的占…

三、W5100S/W5500+RP2040之MicroPython开发<DNS示例>

文章目录 1. 前言2. 相关网络信息2.1 简介2.2 DNS工作过程2.3 优点2.4 应用 3. WIZnet以太网芯片4. DNS解析示例讲解以及使用4.1 程序流程图4.2 测试准备4.3 连接方式4.4 相关代码4.5 烧录验证 5. 注意事项6. 相关链接 1. 前言 在这个智能硬件和物联网时代&#xff0c;MicroPyt…

【一】FPGA实现SPI协议之SPI协议介绍

【一】FPGA实现SPI协议之SPI协议介绍 一、spi协议解析 spi协议有4根线&#xff0c;主机输出从机输入MOSI、主机输入从机输出MISO、时钟信号SCLK、片选信号SS\CS 。 一般用于主机和从机之间通信。由主机发起读请求和写请求&#xff0c;主机的权限是主动的&#xff0c;从机是被…

C/C++编程中的算法实现技巧与案例分析

C/C编程语言因其高效、灵活和底层的特性&#xff0c;被广大开发者用于实现各种复杂算法。本文将通过10个具体的算法案例&#xff0c;详细探讨C/C在算法实现中的技巧和应用。 一、冒泡排序&#xff08;Bubble Sort&#xff09; 冒泡排序&#xff08;Bubble Sort&#xff09;是一…

【Hadoop精讲】HDFS详解

目录 理论知识点 角色功能 元数据持久化 安全模式 SecondaryNameNode(SNN) 副本放置策略 HDFS写流程 HDFS读流程 HA高可用 CPA原则 Paxos算法 HA解决方案 HDFS-Fedration解决方案&#xff08;联邦机制&#xff09; 理论知识点 角色功能 元数据持久化 另一台机器就…