webpack配置完全指南
前言
对于入门选手来讲,webpack 配置项很多很重,如何快速配置一个可用于线上环境的 webpack 就是一件值得思考的事情。其实熟悉 webpack 之后会发现很简单,基础的配置可以分为以下几个方面: entry
、 output
、 mode
、 resolve
、 module
、 optimization
、 plugin
、 source map
、 performance
等,本文就来重点分析下这些部分。
一、配置入口 entry
1、单入口和多入口
将源文件加入到 webpack 构建流程,可以是单入口:
module.exports = {entry: `./index.js`,
}
构建包名称 [name]
为 main
;
或多入口:
module.exports = {entry: { "index": `./index.js`,},
}
key:value
键值对的形式:
- key:构建包名称,即
[name]
,在这里为index
- value:入口路径
入口决定 webapck 从哪个模块开始生成依赖关系图(构建包),每一个入口文件都对应着一个依赖关系图。
2. 动态配置入口文件
动态打包所有子项目
当构建项目包含多个子项目时,每次增加一个子系统都需要将入口文件写入 webpack 配置文件中,其实我们让webpack 动态获取入口文件,例如:
// 使用 glob 等工具使用若干通配符,运行时获得 entry 的条目
module.exports = {entry: glob.sync('./project/**/index.js').reduce((acc, path) => {const entry = path.replace('/index.js', '')acc[entry] = pathreturn acc}, {}),
}
则会将所有匹配 ./project/**/index.js
的文件作为入口文件进行打包,如果你想要增加一个子项目,仅仅需要在 project
创建一个子项目目录,并创建一个 index.js
作为入口文件即可。
这种方式比较适合入口文件不集中且较多的场景。
动态打包某一子项目
在构建多系统应用或组件库时,我们每次打包可能仅仅需要打包某一模块,此时,可以通过命令行的形式请求打印某一模块,例如:
npm run build --project components
在打包的时候解析命令行参数:
// 解析命令行参数
const argv = require('minimist')(process.argv.slice(2))
// 项目
const project = argv['project'] || 'index'
然后配置入口:
module.exports = {entry: { "index": `./${project}/index.js`,}
}
相当于:
module.exports = {entry: { "index": `./components/index.js`,}
}
当然,你可以传入其它参数,也可以应用于多个地方,例如 resolve.alias
中。
二、配置出口 output
用于告知 webpack 如何构建编译后的文件,可以自定义输出文件的位置和名称:
module.exports = {output: { // path 必须为绝对路径// 输出文件路径path: path.resolve(__dirname, '../../dist/build'),// 包名称filename: "[name].bundle.js",// 或使用函数返回名(不常用)// filename: (chunkData) => {// return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js';// },// 块名,公共块名(非入口)chunkFilename: '[name].[chunkhash].bundle.js',// 打包生成的 index.html 文件里面引用资源的前缀// 也为发布到线上资源的 URL 前缀// 使用的是相对路径,默认为 ''publicPath: '/', }
}
在 webpack4 开发模式下,会默认启动 output.pathinfo
,它会输出一些额外的注释信息,对项目调试非常有用,尤其是使用 eval devtool 时。
filename
:[name]
为 entry 配置的 key
,除此之外,还可以是 [id]
(内部块 id )、 [hash]
、[contenthash]
等。
1. 浏览器缓存与 hash 值
对于我们开发的每一个应用,浏览器都会对静态资源进行缓存,如果我们更新了静态资源,而没有更新静态资源名称(或路径),浏览器就可能因为缓存的问题获取不到更新的资源。在我们使用 webpack 进行打包的时候,webpack 提供了 hash 的概念,所以我们可以使用 hash 来打包。
在定义包名称(例如 chunkFilename
、 filename
),我们一般会用到哈希值,不同的哈希值使用的场景不同:
hash
build-specific, 哈希值对应每一次构建( Compilation
),即每次编译都不同,即使文件内容都没有改变,并且所有的资源都共享这一个哈希值,此时,浏览器缓存就没有用了,可以用在开发环境,生产环境不适用。
chunkhash
chunk-specific, 哈希值对应于 webpack 每个入口点,每个入口都有自己的哈希值。如果在某一入口文件创建的关系依赖图上存在文件内容发生了变化,那么相应入口文件的 chunkhash
才会发生变化,适用于生产环境
contenthash
content-specific,根据包内容计算出的哈希值,只要包内容不变,contenthash
就不变,适用于生产环境
webpack 也允许哈希的切片。如果你写 [hash:8]
,那么它会获取哈希值的前 8 位。
注意:
- 尽量在生产环境使用哈希
- 按需加载的块不受
filename
影响,受chunkFilename
影响 - 使用
hash/chunkhash/contenthash
一般会配合html-webpack-plugin
(创建 html ,并捆绑相应的打包文件) 、clean-webpack-plugin
(清除原有打包文件) 一起使用。
2. 打包成库
当使用 webapck 构建一个可以被其它模块引用的库时:
module.exports = {output: { // path 必须为绝对路径// 输出文件路径path: path.resolve(__dirname, '../../dist/build'),// 包名称filename: "[name].bundle.js",// 块名,公共块名(非入口)chunkFilename: '[name].[chunkhash].bundle.js',// 打包生成的 index.html 文件里面引用资源的前缀// 也为发布到线上资源的 URL 前缀// 使用的是相对路径,默认为 ''publicPath: '/', // 一旦设置后该 bundle 将被处理为 librarylibrary: 'webpackNumbers',// export 的 library 的规范,有支持 var, this, commonjs,commonjs2,amd,umdlibraryTarget: 'umd',}
}
三、配置模式 mode(webpack4)
设置 mode
,可以让 webpack 自动调起相应的内置优化。参考 前端进阶面试题详细解答
module.exports = {// 可以是 none、development、production// 默认为 productionmode: 'production'
}
或在命令行里配置:
"build:prod": "webpack --config config/webpack.prod.config.js --mode production"
在设置了 mode
之后,webpack4 会同步配置 process.env.NODE_ENV
为 development
或 production
。
webpack4 最引人注目的主要是:
-
减小编译时间
打包时间减小了超过 60%
-
零配置
我们可以在没有任何配置文件的情况下将 webpack 用于各种项目
webpack4 支持零配置使用,这里的零配置就是指,mode
以及 entry
(默认为 src/index.js
)都可以通过入口文件指定,并且 webpack4 针对对不同的 mode
内置相应的优化策略。
1. production
配置:
// webpack.prod.config.js
module.exports = {mode: 'production',
}
相当于默认内置了:
// webpack.prod.config.js
module.exports = {performance: {// 性能设置,文件打包过大时,会报警告hints: 'warning'},output: {// 打包时,在包中不包含所属模块的信息的注释pathinfo: false},optimization: {// 不使用可读的模块标识符进行调试namedModules: false,// 不使用可读的块标识符进行调试namedChunks: false,// 设置 process.env.NODE_ENV 为 productionnodeEnv: 'production',// 标记块是否是其它块的子集// 控制加载块的大小(加载较大块时,不加载其子集)flagIncludedChunks: true,// 标记模块的加载顺序,使初始包更小occurrenceOrder: true,// 启用副作用sideEffects: true,// 确定每个模块的使用导出,// 不会为未使用的导出生成导出// 最小化的消除死代码// optimization.usedExports 收集的信息将被其他优化或代码生成所使用usedExports: true,// 查找模块图中可以安全的连接到其它模块的片段concatenateModules: true,// SplitChunksPlugin 配置项splitChunks: {// 默认 webpack4 只会对按需加载的代码做分割chunks: 'async',// 表示在压缩前的最小模块大小,默认值是30kbminSize: 30000,minRemainingSize: 0,// 旨在与HTTP/2和长期缓存一起使用 // 它增加了请求数量以实现更好的缓存// 它还可以用于减小文件大小,以加快重建速度。maxSize: 0,// 分割一个模块之前必须共享的最小块数minChunks: 1,// 按需加载时的最大并行请求数maxAsyncRequests: 6,// 入口的最大并行请求数maxInitialRequests: 4,// 界定符automaticNameDelimiter: '~',// 块名最大字符数automaticNameMaxLength: 30,cacheGroups: { // 缓存组vendors: {test: /[\\/]node_modules[\\/]/,priority: -10},default: {minChunks: 2,priority: -20,reuseExistingChunk: true}}},// 当打包时,遇到错误编译,将不会把打包文件输出// 确保 webpack 不会输入任何错误的包noEmitOnErrors: true,checkWasmTypes: true,// 使用 optimization.minimizer || TerserPlugin 来最小化包minimize: true,},plugins: [// 使用 terser 来优化 JavaScriptnew TerserPlugin(/* ... */),// 定义环境变量new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),// 预编译所有模块到一个闭包中,提升代码在浏览器中的执行速度new webpack.optimize.ModuleConcatenationPlugin(),// 在编译出现错误时,使用 NoEmitOnErrorsPlugin 来跳过输出阶段。// 这样可以确保输出资源不会包含错误new webpack.NoEmitOnErrorsPlugin()]
}
2. development
配置:
// webpack.dev.config.js
module.exports = {mode: 'development',
}
相当于默认内置了:
// webpack.dev.config.js
module.exports = {devtool: 'eval',cache: true,performance: {// 性能设置,文件打包过大时,不报错和警告,只做提示hints: false},output: {// 打包时,在包中包含所属模块的信息的注释pathinfo: true},optimization: {// 使用可读的模块标识符进行调试namedModules: true,// 使用可读的块标识符进行调试namedChunks: true,// 设置 process.env.NODE_ENV 为 developmentnodeEnv: 'development',// 不标记块是否是其它块的子集flagIncludedChunks: false,// 不标记模块的加载顺序occurrenceOrder: false,// 不启用副作用sideEffects: false,usedExports: false,concatenateModules: false,splitChunks: {hidePathInfo: false,minSize: 10000,maxAsyncRequests: Infinity,maxInitialRequests: Infinity,},// 当打包时,遇到错误编译,仍把打包文件输出noEmitOnErrors: false,checkWasmTypes: false,// 不使用 optimization.minimizer || TerserPlugin 来最小化包minimize: false,removeAvailableModules: false},plugins: [// 当启用 HMR 时,使用该插件会显示模块的相对路径// 建议用于开发环境new webpack.NamedModulesPlugin(),// webpack 内部维护了一个自增的 id,每个 chunk 都有一个 id。// 所以当增加 entry 或者其他类型 chunk 的时候,id 就会变化,// 导致内容没有变化的 chunk 的 id 也发生了变化// NamedChunksPlugin 将内部 chunk id 映射成一个字符串标识符(模块的相对路径)// 这样 chunk id 就稳定了下来new webpack.NamedChunksPlugin(),// 定义环境变量new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),]
}
3. none
不进行任何默认优化选项。
配置:
// webpack.com.config.js
module.exports = {mode: 'none',
}
相当于默认内置了:
// webpack.com.config.js
module.exports = {performance: {// 性能设置,文件打包过大时,不报错和警告,只做提示hints: false},optimization: {// 不标记块是否是其它块的子集flagIncludedChunks: false,// 不标记模块的加载顺序occurrenceOrder: false,// 不启用副作用sideEffects: false,usedExports: false,concatenateModules: false,splitChunks: {hidePathInfo: false,minSize: 10000,maxAsyncRequests: Infinity,maxInitialRequests: Infinity,},// 当打包时,遇到错误编译,仍把打包文件输出noEmitOnErrors: false,checkWasmTypes: false,// 不使用 optimization.minimizer || TerserPlugin 来最小化包minimize: false,},plugins: []
}
4. production、 development、none 总结
production 模式下给你更好的用户体验:
- 较小的输出包体积
- 浏览器中更快的代码执行速度
- 忽略开发中的代码
- 不公开源代码或文件路径
- 易于使用的输出资产
development 模式会给予你最好的开发体验:
- 浏览器调试工具
- 快速增量编译可加快开发周期
- 运行时提供有用的错误消息
尽管 webpack4 在尽力让零配置做到更多,但仍然是有限度的,大多数情况下还是需要一个配置文件。我们可以在项目的初期使用零配置,在后期业务复杂的时候再配置。
5. 环境变量 process.env.NODE_ENV
第三方框架或库,以及我们的业务代码,都会针对不同的环境配置,执行不同的逻辑代码,例如:
我们可以通过以下方式定义环境变量:
方法一:webpack4 中 mode: ‘production’ 已经默认配置了 process.env.NODE_ENV = ‘production’ ,所以 webapck4 可以不定义
尽管 webpack4 中定义 mode
会自动配置 process.env.NODE_ENV
,那么我们就不需要手动配置环境变量了吗?
其实不然,mode
只可以定义成 development
或 production
,而在项目中,我们不仅仅只有开发或生产环境,很多情况下需要配置不同的环境(例如测试环境),此时我们就需要手动配置其它环境变量(例如测试环境,就需要定义 process.env.NODE_ENV
为 'test'
),你可以采取以下方式:
方法二:webpack.DefinePlugin
// webpack编译过程中设置全局变量process.env
new webpack.DefinePlugin({'process.env': require('../config/dev.env.js')
}
config/prod.env.js
:
module.exports ={// 或 '"production"' ,环境变量的值需要是一个由双引号包裹的字符串NODE_ENV: JSON.stringify('production')
}
方法三:webpack 命令时, NODE_ENV=development
在 window 中配置 NODE_ENV=production
可能会卡住,所以使用 cross-env:
cross-env NODE_ENV=production webpack --config webpack.config.prod.js
方法四:使用 new webpack.EnvironmentPlugin(['NODE_ENV'])
EnvironmentPlugin
是一个通过 webpack.DefinePlugin
来设置 process.env
环境变量的快捷方式。
new webpack.EnvironmentPlugin({NODE_ENV: 'production',
});
注意:上面其实是给 NODE_ENV
设置一个默认值 'production'
,如果其它地方有定义 process.env.NODE_ENV
,则该默认值无效。
四、配置解析策略 resolve
自定义寻找依赖模块时的策略(例如 import _ from 'lodash'
):
module.exports = {resolve: {// 设置模块导入规则,import/require时会直接在这些目录找文件// 可以指明存放第三方模块的绝对路径,以减少寻找,// 默认 node_modulesmodules: [path.resolve(`${project}/components`), 'node_modules'],// import导入时省略后缀// 注意:尽可能的减少后缀尝试的可能性extensions: ['.js', '.jsx', '.react.js', '.css', '.json'],// import导入时别名,减少耗时的递归解析操作alias: {'@components': path.resolve(`${project}/components`),'@style': path.resolve('asset/style'),},// 很多第三方库会针对不同的环境提供几份代码// webpack 会根据 mainFields 的配置去决定优先采用那份代码// 它会根据 webpack 配置中指定的 target 不同,默认值也会有所不同mainFields: ['browser', 'module', 'main'],},
}
五、配置解析和转换文件的策略 module
决定如何处理项目中不同类型的模块,通常是配置 module.rules 里的 Loader:
module.exports = {module: {// 指明 webpack 不去解析某些内容,该方式有助于提升 webpack 的构建性能noParse: /jquery/,rules: [{// 这里编译 js、jsx// 注意:如果项目源码中没有 jsx 文件就不要写 /\.jsx?$/,提升正则表达式性能test: /\.(js|jsx)$/,// 指定要用什么 loader 及其相关 loader 配置use: {loader: "babel-loader",options: {// babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启// 使用 cacheDirectory 选项将 babel-loader 的速度提高2倍cacheDirectory: true,// Save disk space when time isn't as importantcacheCompression: true,compact: true, }},// 排除 node_modules 目录下的文件// node_modules 目录下的文件都是采用的 ES5 语法,没必要再通过 Babel 去转换exclude: /node_modules/// 也可以配置 include:需要引入的文件}]}
}
1. noParse
指明 webpack 不去解析某些内容,该方式有助于提升 webpack 的构建性能。
2. rules
常见的 loader 有:
-
babel-loader
:解析.js
和.jsx
文件// 配置 .babelrc {"presets": [["@babel/preset-env",],"@babel/preset-react"],"plugins": [["@babel/plugin-proposal-class-properties",{"loose": true}],["@babel/plugin-transform-runtime",{"absoluteRuntime": false,"corejs": false,"helpers": true,"regenerator": true,"useESModules": false}],] }
-
tsx-loader
:处理 ts 文件 -
less-loader
:处理 less 文件,并将其编译为 css -
sass-loader
:处理 sass、scss 文件,并将其编译为 css -
postcss-loader
:// postcss.config.js module.exports = { // 解析CSS文件并且添加浏览器前缀到 CSS 内容里plugins: [require('autoprefixer')], };
-
css-loader
:处理 css 文件 -
style-loader
:将 css 注入到 DOM -
file-loader
:将文件上的import
/require
解析为url
,并将该文件输出到输出目录中 -
url-loader
:用于将文件转换成 base64 uri 的 webpack 加载程序 -
html-loader
:将 HTML 导出为字符串, 当编译器要求时,将 HTML 最小化
六、配置优化 optimization(webpack4)
webapck4 会根据你所选择的 mode
进行优化,你可以手动配置,它将会覆盖自动优化
主要涉及两方面的优化:
- 最小化包
- 拆包
1. 最小化包
- 使用
optimization.removeAvailableModules
删除已可用模块 - 使用
optimization.removeEmptyChunks
删除空模块 - 使用
optimization.occurrenceOrder
标记模块的加载顺序,使初始包更小 - 使用
optimization.providedExports
、optimization.usedExports
、concatenateModules
、optimization.sideEffects
删除死代码 - 使用
optimization.splitChunks
提取公共包 - 使用
optimization.minimizer
||TerserPlugin
来最小化包
2. 拆包
当包过大时,如果我们更新一小部分的包内容,那么整个包都需要重新加载,如果我们把这个包拆分,那么我们仅仅需要重新加载发生内容变更的包,而不是所有包,有效的利用了缓存。
拆分 node_modules
很多情况下,我们不需要手动拆分包,可以使用 optimization.splitChunks
:
const path = require('path');
module.exports = {entry: path.resolve(__dirname, 'src/index.js'),output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[contenthash].js',},optimization: {splitChunks: {// 对所有的包进行拆分chunks: 'all',},},
};
我们不必制定拆包策略,chunks: all
会自动将 node_modules
中的所有内容放入一个名为 vendors〜main.js
的文件中。
拆分业务代码
module.exports = {entry: {main: path.resolve(__dirname, 'src/index.js'),ProductList: path.resolve(__dirname, 'src/ProductList/ProductList.js'),ProductPage: path.resolve(__dirname, 'src/ProductPage/ProductPage.js'),Icon: path.resolve(__dirname, 'src/Icon/Icon.js'),},output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[contenthash:8].js',},
};
采用多入口的方式,当有业务代码更新时,更新相应的包即可
拆分第三方库
const path = require('path');
const webpack = require('webpack');module.exports = {entry: path.resolve(__dirname, 'src/index.js'),output: {path: path.resolve(__dirname, 'dist'),filename: '[name].[contenthash].js',},optimization: {runtimeChunk: 'single',splitChunks: {chunks: 'all',maxInitialRequests: Infinity,minSize: 0,cacheGroups: {vendor: {test: /[\\/]node_modules[\\/]/,name(module) {// 获取第三方包名const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];// npm 软件包名称是 URL 安全的,但是某些服务器不喜欢@符号return `npm.${packageName.replace('@', '')}`;},},},},},
};
当第三方包更新时,仅更新相应的包即可。
注意,当包太多时,浏览器会发起更多的请求,并且当文件过小时,对代码压缩也有影响。
动态加载
现在我们已经对包拆分的很彻底了,但以上的拆分仅仅是对浏览器缓存方面的优化,减小首屏加载时间,实际上我们也可以使用按需加载的方式来进一步拆分,减小首屏加载时间:
import React, { useState, useEffect } from 'react';
import './index.scss'function Main() {const [NeighborPage, setNeighborPage] = useState(null)useEffect(() => {import('../neighbor').then(({ default: component }) => {setNeighborPage(React.createElement(component))});}, [])return NeighborPage? NeighborPage: <div>Loading...</div>;
}export default Main
七、配置 plugin
配置 Plugin 去处理及优化其它的需求,
module.exports = {plugins: [// 优化 requirenew webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en|zh/),// 用于提升构建速度createHappyPlugin('happy-babel', [{loader: 'babel-loader',options: {presets: ['@babel/preset-env', "@babel/preset-react"],plugins: [['@babel/plugin-proposal-class-properties', {loose: true}]],// babel-loader 支持缓存转换出的结果,通过 cacheDirectory 选项开启cacheDirectory: true,// Save disk space when time isn't as importantcacheCompression: true,compact: true,}}])]
}
常用 plugins:
html-webpack-plugin
:生成 html 文件,并将包添加到 html 中webpack-parallel-uglify-plugin
:压缩 js(多进程并行处理压缩)happypack
:多线程loader,用于提升构建速度hard-source-webpack-plugin
:为模块提供中间缓存步骤,显著提高打包速度webpack-merge
:合并 webpack 配置mini-css-extract-plugin
:抽离 cssoptimize-css-assets-webpack-plugin
:压缩 cssadd-asset-html-webpack-plugin
:将 JavaScript 或 CSS 资产添加到 html-webpack-plugin 生成的 HTML 中
更多插件可见:plugins
八、配置devtool:source map
配置 webpack 如何生成 Source Map,用来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度:
生产环境:默认为 null
,一般不设置( none
)或 nosources-source-map
开发环境:默认为 eval
,一般设置为 eval
、 cheap-eval-source-map
、cheap-module-eval-source-map
策略为:
- 使用 cheap 模式可以大幅提高 souremap 生成的效率。 没有列信息(会映射到转换后的代码,而不是映射到原始代码),通常我们调试并不关心列信息,而且就算 source map 没有列,有些浏览器引擎(例如 v8) 也会给出列信息。
- **使用 eval 方式可大幅提高持续构建效率。**参考官方文档提供的速度对比表格可以看到 eval 模式的编译速度很快。
- 使用 module 可支持 babel 这种预编译工具(在 webpack 里做为 loader 使用)。
如果默认的 webpack minimizer
已经被重定义(例如 terser-webpack-plugin
),你必须提供 sourceMap:true
选项来启用 source map 支持。
九、配置性能 performance
当打包是出现超过特定文件限制的资产和入口点,performance
控制 webpack 如何通知:
module.exports = {// 配置如何显示性能提示performance: {// 可选 warning、error、false// false:性能设置,文件打包过大时,不报错和警告,只做提示// warning:显示警告,建议用在开发环境// error:显示错误,建议用在生产环境,防止部署太大的生产包,从而影响网页性能hints: false}
}
十、配置其它
1. watch 与 watchOptions
watch
监视文件更新,并在文件更新时重新编译:
module.export = {// 启用监听模式watch: true,
}
在 webpack-dev-server
和 webpack-dev-middleware
中,默认启用了监视模式。
或者我们可以在命令行里启动监听( --watch
):
webpack --watch --config webpack.config.dev.js
watchOptions
module.export = {watch: true,// 自定义监视模式watchOptions: {// 排除监听ignored: /node_modules/,// 监听到变化发生后,延迟 300ms(默认) 再去执行动作,// 防止文件更新太快导致重新编译频率太高aggregateTimeout: 300,// 判断文件是否发生变化是通过不停的去询问系统指定文件有没有变化实现的// 默认 1000ms 询问一次poll: 1000}
}
2. externals
排除打包时的依赖项,不纳入打包范围内,例如你项目中使用了 jquery
,并且你在 html 中引入了它,那么在打包时就不需要再把它打包进去:
<scriptsrc="https://code.jquery.com/jquery-3.1.0.js"integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="crossorigin="anonymous">
</script>
配置:
module.exports = {// 打包时排除 jquery 模块externals: {jquery: 'jQuery'}
};
3.target
构建目标,用于为 webpack 指定一个环境:
module.exports = {// 编译为类浏览器环境里可用(默认)target: 'web'
};
4. cache
缓存生成的 webpack 模块和块以提高构建速度。在开发模式中,缓存设置为 type: 'memory'
,在生产模式中禁用。cache: true
是 cache: {type: 'memory'}
的别名。要禁用缓存传递 false
:
module.exports = {cache: false
}
在内存中,缓存仅在监视模式下有用,并且我们假设你在开发中使用监视模式。 在不进行缓存的情况下,内存占用空间较小。
5. name
配置的名称,用于加载多个配置:
module.exports = {name: 'admin-app'
};
相关文章:
webpack配置完全指南
前言 对于入门选手来讲,webpack 配置项很多很重,如何快速配置一个可用于线上环境的 webpack 就是一件值得思考的事情。其实熟悉 webpack 之后会发现很简单,基础的配置可以分为以下几个方面: entry 、 output 、 mode 、 resolve …...
juju创建lxd容器时如何使用本地镜像(by quqi99)
作者:张华 发表于:2023-03-01 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 问题 没有外网,所以配置了一个local custom镜像库,也使用了container-image-meta…...
后端程序员学习前端开发之第一步环境搭建
一、安装 Node.js Node.js 是一个开源的、跨平台的 JavaScript 运行时环境。Node.js官网 二、安装 npm 镜像 因为 npm 是国外的,所以使用起来速度比较慢。我们这里使用了淘宝的 cnpm 镜像安装 vue。使用淘宝的 cnpm 命令管理工具代替默认的 npm 管理工具。 进入c…...
【记录问题】RuntimeError:working outside of application context. Flask使用SQLAlchemy数据库
前提:Flask使用SQLAlchemy数据库 本质:依赖包版本不匹配 问题1:报错RuntimeError:working outside of application context. 运行程序报错,如下错误: 原因:flask-sqlalchemy 版本过高导致&am…...
自动化测试难点案例分析,其实自动化你用错方向还不如不用
随着国内企业软件开发及测试水平的提升,许多企业开始尝试开展自动化测试的应用,以提高测试效率和测试质量。虽然在国外自动化测试工具应用已经很普遍,但国内许多企业对于软件自动化测试的理解还停留在表面上,没有深入的理解到企业…...
866363-70-4,N3-C5-NHS ester,叠氮-C5-NHS 主要物理性质分享
●外观以及性质:Azido-Aca-NHS淡黄色或无色油状,叠氮化物可以与炔烃、DBCO和BCN进行铜催化的点击化学反应。NHS酯可以与胺基反应,形成稳定的酰胺键。●中文名:叠氮-C5-NHS ester,6-叠氮己酸活性酯●英文名:…...
字符流定义及如何深入理解字符流的编码
IputSrem类和OupuSrem类在读写文件时操作的都是字节,如果希望在程序中操作字符,使用这两个类就不太方便,为此JDK提供了字符流。同字节流样,字符流也有两个抽象的顶级父类,分别是Reader和Writer其中,Reader是…...
什么是pod类型
很久很久以前,C 语言统一了江湖。几乎所有的系统底层都是用 C 写的,当时定义的基本数据类型有 int、char、float 等整数类型、浮点类型、枚举、void、指针、数组、结构等等。然后只要碰到一串01010110010 之类的数据,编译器都可以正确的把它解…...
2023年中小企业实施智能制造的建议
智能制造的载体是制造系统,制造系统从微观到宏观有不同的层次,主要包括制造装备、制造单元、制造车间(工厂)、制造企业和企业生态等。随着智能制造的深入推进,未来智能制造将向以下五个方向发展。 (一&…...
【LeetCode】剑指 Offer 19. 正则表达式匹配 p124 -- Java Version
题目链接:https://leetcode.cn/problems/zheng-ze-biao-da-shi-pi-pei-lcof/ 1. 题目介绍(19. 正则表达式匹配) 请实现一个函数用来匹配包含. 和*的正则表达式。模式中的字符.表示任意一个字符,而’*表示它前面的字符可以出现任意…...
linux和windows中安装emqx消息服务器
大家好,我是雄雄,欢迎关注微信公众号雄雄的小课堂 现在是:2023年3月1日21:53:55 前言 最近几天看了下mqtt,通过不断的搜索资料,也将mqtt集成到项目中,跑了个demo运行,和预想中的差不多&#x…...
【XXL-JOB】XXL-JOB的搭建和使用
【XXL-JOB】XXL-JOB的搭建和使用 文章目录【XXL-JOB】XXL-JOB的搭建和使用1. 任务调度1.1 实现任务调度1.1.1 多线程实现1.1.2 Timer实现1.1.3 ScheduledExecutor实现2. 分布式任务调度2.1 采用分布式的原因3. XXL-JOB3.1 XXL-JOB介绍3.2 执行流程4. 搭建XXL-JOB4.1 创建数据库…...
HCIP-5OSPF基本原理及基本配置学习笔记
1、OSPF基本原理 开放式最短路径优先OSPF(Open Shortest Path First)协议是IETF定义的一种基于链路状态的内部网关路由协议。 RIP是一种基于距离矢量算法的路由协议,存在着收敛慢、易产生路由环路、可扩展性差等问题,目前已逐渐被…...
Migrate your data into databend with DataX
现在互联网应用越来越复杂,每个公司都会有多种多样的数据库。通常是用最好的硬件来跑 OLTP,甚至还在 OLTP 中进行分库分表来满足业务,这样对于一些分析,聚合,排序操作非常麻烦。这也有了异构数据库的数据同步需求&…...
ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password)
【ansible 设置host为localhost,执行ping命令报错】 [eniq-slocalhost ansible]$ ansible all -m ping -i inventory localhost | UNREACHABLE! > { "changed": false, "msg": "Failed to connect to the host via ssh: Perm…...
有限元中三角形的一些积分公式
文章目录有限元中三角形的相关积分公式有限元中三角形的相关积分公式 在 xyxyxy 平面中, 通过三个点 (xi,yi),(xj,yj),(xm,ym)(x_i, y_i), (x_j, y_j), (x_m, y_m)(xi,yi),(xj,yj),(xm,ym) 定义一个三角形, 令坐标原点位于其中心(或者重心)…...
【docker-compose】安装mongodb
1. 安装方式 压缩包容器安装docker(推荐,一分钟安装) 2. 环境 linux服务器已安装好 docker docker-compose (不了解的客官,请点击进入) 3. 步骤: Step 1: linux下建立如下目录…...
【ClickHouse源码】物化视图的写入过程
本文对 ClickHouse 物化视图的写入流程源码做个详细说明,基于 v22.8.14.53-lts 版本。 StorageMaterializedView 首先来看物化视图的构造函数: StorageMaterializedView::StorageMaterializedView(const StorageID & table_id_,ContextPtr local_…...
.NET 使用NLog增强日志输出
引言 不管你是开发单体应用还是微服务应用,在实际的软件的开发、测试和运行阶段,开发者都需要借助日志来定位问题。因此一款好的日志组件将至关重要,在.NET 的开源生态中,目前主要有Serilog、Log4Net和NLog三款优秀的日志组件&…...
一道阿里类的初始化顺序笔试题
问题很简单,就是下面的代码打印出什么? public class InitializeDemo {private static int k 1;private static InitializeDemo t1 new InitializeDemo("t1" );private static InitializeDemo t2 new InitializeDemo("t2");priv…...
cuda找不到路径报错
编译C文件时出现:error: [Errno 2] No such file or directory: :/usr/local/cuda:/usr/local/cuda/bin/nvcc 在终端输入: export CUDA_HOME/usr/local/cuda...
Elasticsearch进阶之(核心概念、系统架构、路由计算、倒排索引、分词、Kibana)
Elasticsearch进阶之(核心概念、系统架构、路由计算、倒排索引、分词、Kibana) 1、核心概念: 1.1、索引(Index) 一个索引就是一个拥有几分相似特征的文档的集合。比如说,你可以有一个客户数据的索引&…...
Android包体积缩减
关于减小包体积的方案: 一、所有的图片压缩,采用webp 格式。 (当然有些图片采用webp格式反而变大了,可以仍采用png格式) 二、语音资源过滤 只保留中文 resConfigs "zh-rCN", "zh” 可以减少resourc…...
【华为OD机试】 网上商城优惠活动(C++ Java Javascript Python)
文章目录 题目描述输入描述输出描述备注用例题目解析C++JavaScriptJavaPython题目描述 某网上商场举办优惠活动,发布了满减、打折、无门槛3种优惠券,分别为: 每满100元优惠10元,无使用数限制,如100199元可以使用1张减10元,200299可使用2张减20元,以此类推;92折券,1次…...
GWT安装过程
1:安装前准备 (可以问我要) appengine-java-sdk-1.9.8 com.google.gdt.eclipse.suite.4.3.update.site_3.8.0 gwt-2.5.1 eclipse-jee-kepler-SR2-win32-x86_64.zip 2:安装环境上 打开eclipse Help –Install New Software… 选择Add –…...
代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
Leetcode 704 二分查找题目链接:704二分查找介绍给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。思路先看看一个…...
office@word@ppt启用mathtype组件方法整理
文章目录将mathtype添加到word中ref查看office安装路径文件操作法Note附PPT中使用mathtype将mathtype添加到word中 先安装office,再安装mathtype,那么这个过程是自动的如果是先安装mathtype,再安装office,那么有以下选择: 重新安装一遍mathtype(比较简单,不需要说明)执行文件操…...
计算机大小端
我们先假定内存结构为上下型的,上代表内存高地址,下代表内存低地址。 电脑读取内存数据时,是从低位地址到高位地址进行读取(从下到上)。 1、何为大小端 大端:数据的高位字节存放在低地址,数据…...
Matplotlib绘图从零入门到实践(含各类用法详解)
一、引入 Matplotlib 是一个Python的综合库,用于在 Python 中创建静态、动画和交互式可视化。 本教程包含笔者在使用Matplotlib库过程中遇到的各类完整实例与用法还有遇到的库理论问题,可以根据自己的需要在目录中查询对应的用法、实例以及第四部分关于…...
C语言 入门教程||C语言 指针||C语言 字符串
C语言 指针 学习 C 语言的指针既简单又有趣。通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。 …...
深圳品牌模板网站建设/哈尔滨新闻头条今日新闻
一、什么是跨域问题 当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域 如图:我们的vue前端项目的端口号为8081,ssm后端项目的端口号为8080,恭喜你出现跨域问题了! 这时,我们可能会想到改…...
上海进博会?/廊坊自动seo
ASP.NET Core断点续传 在ASP.NET WebAPi写过完整的断点续传文章,目前我对ASP.NET Core仅止于整体上会用,对于原理还未去深入学习,由于有园友想看断点续传在ASP.NET Core中的具体实现,于是借助在家中休息时间看了下ASP.NET Core是否…...
上海网站建设免费推荐/免费b站在线观看人数在哪里找到
目录 一、软件测试的生命周期 二、如何描述一个bug 一、软件测试的生命周期 软件测试的生命周期: 需求分析→测试计划→ 测试设计、测试开发→ 测试执行→ 测试评估 需求阶段 –测试人员了解需求、对需求进行分解,得出测试需求 计划阶段 -根据需求编写…...
网站建设 asp 武汉/天眼查企业查询入口
功能需求: 在监督监理项目的Word报告模块中,要求实现对Word文件内容操作的撤销、重做功能。 实施方案: 采用备忘录模式实现。 要点一:备忘录模式 应用程序在每次操作之后都改变了他的状态。也就是说一个应用程序一旦被操作&#x…...
app分销商城系统/宁波seo排名优化培训
// 适配器 Adapter类中简要代码 Context mContext;//获取环境上下文 //设置领用日期holder.tvDate.setOnClickListener(new View.OnClickListener() {Overridepublic void onClick(View v) {Toast.makeText(mContext.getApplicationContext(), "预约时间无效,请…...
企业公司黄页大全/长沙网站seo优化公司
- 前言 -大家都知道,计算机的瓶颈之一就是IO,为了解决内存与磁盘速度不匹配的问题,产生了缓存,将一些热点数据放在内存中,随用随取,降低连接到数据库的请求链接,避免数据库挂掉。需要注意的是&#…...