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.五个核心概念:
- 【入口(entry)】:指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
- 【输出(output)】:在哪里输出文件,以及如何命名这些文件。
- 【Loader】:处理那些非 JavaScript 文件(webpack 自身只能解析 JavaScript和json)。
- 【插件(plugins)】执行范围更广的任务,从打包到优化都可以实现。
- 【模式(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')}
})
相关文章:

webpack知识点总结(基础应用篇)
一、为什么需要webpack 1.为什么使用webpack ①传统的书写方式,加载太多脚本会导致网络瓶颈,如不小心改变JavaScript文件加载顺序,项目会崩溃,还会导致作用域问题、js文件太大无法做到按需加载、可读性和可维护性太低的问题。 ②…...

监控k8s controller和scheduler,创建serviceMonitor以及Rules
目录 一、修改kube-controller和kube-schduler的yaml文件 二、创建service、endpoint、serviceMonitor 三、Prometheus验证 四、创建PrometheusRule资源 五、Prometheus验证 直接上干货 一、修改kube-controller和kube-schduler的yaml文件 注意:修改时要一个节…...

支持向量机 支持向量机概述
支持向量机概述 支持向量机 Support Vector MachineSVM ) 是一类按监督学习 ( supervisedlearning)方式对数据进行二元分类的广义线性分类器 (generalized linear classifier) ,其决策边界是对学习样本求解的最大边距超亚面 (maximum-margin hyperplane)与逻辑回归和…...

http -- 跨域问题详解(浏览器)
参考链接 参考链接 1. 跨域报错示例 Access to XMLHttpRequest at http://127.0.0.1:3000/ from origin http://localhost:3000 has been blocked by CORS policy: Response to preflight request doesnt pass access control check: No Access-Control-Allow-Origin header…...

Java对接腾讯多人音视频房间回调接口示例
在前面我们已经对接好了腾讯多人音视频房间相关内容:Java对接腾讯多人音视频房间示例 为了完善业务逻辑,我们还需要对接它的一些回调接口 官方文档地址 主要就下面这些 这里因为比较简单直接上代码 里面有些工具类和上一章一样这里就没贴,需要…...

vp与vs联合开发-通过FrameGrabber连接相机
添加控件 1.CogRecordDisplay 控件 用于显示图像 初始化相机对象方法 //启动窗体时 调用初始化相机方法 //封装相机关闭方法 //窗体关闭时 调用相机关闭方法 拍照 设置采图事件 // 保存图像 设置曝光按钮事件 1.可变参数...

音视频直播核心技术介绍
直播流程 采集: 是视频直播开始的第一个环节,用户可以通过不同的终端采集视频,比如 iOS、Android、Mac、Windows 等。 前处理:主要就是美颜美型技术,以及还有加水印、模糊、去噪、滤镜等图像处理技术等等。 编码&#…...

JNDI注入Log4jFastJson白盒审计不回显处理
目录 0x00 前言 0x01 Maven 仓库及配置 0x02 JNDI 注入简介 0x03 Java-第三方组件-Log4J&JNDI 0x04 Java-第三方组件-FastJson&反射 0x05 白盒审计 - FastJson 0x06 白盒审计 - Log4j 0x07 不回显的处理方法 0x00 前言 希望和各位大佬一起学习,如果…...

FPGA实现腐蚀和膨胀算法verilog设计及仿真 加报告
要在FPGA上实现腐蚀和膨胀算法,你可以按照以下步骤进行: 图像存储:首先,你需要设计一个图像存储器来存储待处理的图像数据。这可以采用FPGA内部存储器或外部存储器。 读取图像数据:使用适当的接口从图像存储器中读取图像数据,并将其加载到FPGA的计算单元中。 结构元素定义…...

核和值域的关系:什么是矩阵的秩?
核和值域的关系:什么是矩阵的秩? 这篇博客将介绍一个任意矩阵的核和值域的关系,并由此说明矩阵秩的意义、子空间维数、子空间正交。 1、矩阵的核:N(A) A ∈ C m n A\in C^{m\times n} A∈Cmn,矩阵的核,记…...

【MyBatis Plus】Service Mapper内置接口讲解
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟推荐给大家我的专栏《MyBatis-Plus》。🎯🎯 &am…...

制作一个简单 的maven plugin
流程 首先, 你需要创建一个Maven项目,推荐用idea 创建项目 会自动配置插件 pom.xml文件中添加以下配置: <project> <!-- 项目的基本信息 --> <groupId>com.example</groupId> <artifactId>my-maven-plugi…...

基于linux系统的Tomcat+Mysql+Jdk环境搭建(三)centos7 安装Tomcat
Tomcat下载官网: Apache Tomcat - Which Version Do I Want? JDK下载官网: Java Downloads | Oracle 中国 如果不知道Tomcat的哪个版本应该对应哪个版本的JDK可以打开官网,点击Whitch Version 下滑,有低版本的,如…...

Ubuntu环境下SomeIP/CommonAPI环境搭建详细步骤
环境搭建 1.Boost安装 下载Boost源码 : https://www.boost.org/users/download/ 编译安装 首先安装编译所需依赖 sudo apt-get install build-essential g sudo apt-get install installpython-dev autotools-dev sudo apt-get install installlibicu-dev buil…...

maven 项目导入异常问题
问题如下 一、 tomcat正再运行的包是哪一个 不同构建、打包情况下分别运行 out\artifacts下 当直接去Project Structure下去构建artifacts 后,运行tomcat 则会在out下target下 reimport项目后,则会在artifacts自动生成部署包。删除tomcat之前deployment 下的包(同…...

在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装教程
在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装教程 VMware 虚拟机解锁 macOS 安装选项使用 macOS iso 系统镜像安装使用 OpenCore 做引导程序安装 在 VMware 虚拟机上安装黑苹果(Hackintosh):免费 macOS ISO 镜像下载及安装…...

国产ToolLLM的课代表---OpenBMB机构(清华NLP)旗下ToolBench的安装部署与运行(附各种填坑说明)
ToolBench项目可以理解为一个能直接提供训练ToolLLM的平台,该平台同时构建了ToolLLM的一个开源训练指令集。,该项目是OpenBMB机构(面壁智能与清华NLP联合成立)旗下的一款产品,OpenBMB机构名下还同时拥有另外一款明星产…...

串口通信(5)-C#串口通信数据接收不完整解决方案
本文讲解C#串口通信数据接收不完整解决方案。 目录 一、概述 二、Modbus RTU介绍 三、解决思路 四、实例 一、概述 串口处理接收数据是串口程序编写的关键...

大数据分析岗是干什么的?
大数据分析岗主要负责从大规模数据集中提取、整理、分析和解释有关业务、市场或其他相关领域的信息的职位。 主要的职责和工作内容如下: 1. 数据收集和整理 收集各种数据源(包括结构化、非结构化和半结构化数据),并将其整理成可…...

hadoop运行jar遇到的一个报错
报错信息: 2023-12-19 14:28:25,893 INFO mapreduce.Job: Job job_1702967272525_0001 failed with state FAILED due to: Application application_1702967272525_0001 failed 2 times due to AM Container for appattempt_1702967272525_0001_000002 exited with…...

长短期记忆(LSTM)神经网络-多输入分类
目录 一、程序及算法内容介绍: 基本内容: 亮点与优势: 二、实际运行效果: 三、部分程序: 四、完整程序下载: 一、程序及算法内容介绍: 基本内容: 本代码基于Matlab平台编译&am…...

开启创意之旅:免费、开源的噪波贴图(noise texture)生成网站——noisecreater.com详细介绍
在当今数字创意领域,噪波贴图(Noise Texture)是游戏渲染、游戏开发、美术设计以及影视制作等行业不可或缺的艺术素材之一。为了满足广大创作者的需求,noisecreater.com应运而生,成为一款免费、开源的噪波贴图生成工具。…...

Android Studio问题解决:Gradle Download 下载超时 Connect reset
文章目录 一、遇到问题二、解决办法 一、遇到问题 Gradle Download下载超时Sync了很多次,一直失败 二、解决办法 手动通过gradle网站下载 https://gradle.org/releases/可能也会出现超时,最好开个VPN软件会比较快。 下载好的软件,放到本机的…...

【Python百宝箱】云上翱翔:Python编程者的AWS奇妙之旅
雲端箴言:用Python主持AWS管理交響樂 前言 随着云计算的普及,AWS(Amazon Web Services)成为了许多组织和开发者首选的云服务提供商。作为Python工程师,深入了解AWS管理工具和库对于高效利用云资源至关重要。本文将引…...

抖音直播间websocket礼物和弹幕消息推送可能出现重复的情况,解决办法
在抖音直播间里,通过websocket收到的礼物消息数据格式如下: {common: {method: WebcastGiftMessage,msgId: 7283420150152942632,roomId: 7283413007005207308,createTime: 1695803662805,isShowMsg: True,describe: 莎***:送给主播 1个入团卡,priority…...

【设计模式--行为型--访问者模式】
设计模式--行为型--访问者模式 访问者模式定义结构案例优缺点使用场景扩展分派动态分派静态分派双分派 访问者模式 定义 封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下定义作用于这些元素的新操作。 结构 抽象访问者角色&…...

[最后一个月征稿、ACM独立出版】第三届密码学、网络安全和通信技术国际会议(CNSCT 2024)
第三届密码学、网络安全和通信技术国际会议(CNSCT 2024) 2024 3rd International Conference on Cryptography, Network Security and Communication Technology 一、大会简介 随着互联网和网络应用的不断发展,网络安全在计算机科学中的地…...

android —— PopupWindow
一、常用方法: 1、设置显示的位置 // 一个参数 popupWindow.showAsDropDown(v); //参数1: popupWindow关联的view // 参数2和3:相对于关联控件的偏移量popupWindow.showAsDropDown(View anchor, int xoff, int yoff)2、是否会获取焦点 popupWindow.se…...

mysql部署 --(docker)
先查找MySQL 镜像 Docker search mysql ; 拉取mysql镜像,默认拉取最新的; 创建mysql容器,-p 代表端口映射,格式为 宿主机端口:容器运行端口 -e 代表添加环境变量,MYSQL_ROOT_PASSWORD是root用户…...

基于多智能体系统一致性算法的电力系统分布式经济调度策略MATLAB程序
微❤关注“电气仔推送”获得资料(专享优惠) 参考文献: 主要内容: 应用多智能体系统中的一致性算法,以发电机组的增量成本和柔性负荷的增量效益作为一致性变量,设计一种用于电力系统经济调度的算法&#x…...