重构Webpack系列之六 ---- 配置文件

一、基本用法

webpack的配置文件不尽相同。这是因为webpack的配置文件是JavaScript文件,文件内导出了一个webpack配置的对象,然后webpack会根据该配置定义的属性进行处理。

本文的结论是,webpack的配置可以有许多不同的样式和风格。关键在于,为了易于维护和理解这些配置,需要再团队内部保持一致。本文基于webpack@5版本进行操作说明。

a.基本配置

const path = require('path');module.exports = {mode: 'development',entry: './foo.js',output: {path: path.resolve(__dirname,'dist'),filename: 'foo.bundle.js'}
}

b.不同的配置文件

一般开发项目的过程中,会区分开发环境和生产环境,所以webpack对应的配置文件也要分开:

// package.json"scripts": {"build": "webpack --config webpack.prod.config.js","dev": "webpack --config webpack.dev.config.js"
}

c.其他配置

webpack完整的配置文件还有很多选项,让我们一一了解他:

const path = require('path');module.exports = {mode: "production", //"production" | "development" | "none"// 选择不同的模式告诉webpack相应地使用其内置优化。entry: "./app/entry.js", // string | object | array// 默认为./src,这里应用程序开始执行,webpack开始打包output: {// webpack输出结果的相关选项path: path.resolve(__dirname, "dist"),// 所有输出文件的目标路径,必须是绝对路径(使用nodejs的path模块)filename: "[name].js", // string(default)// entry chunk的文件名模板publicPath: "/assets/", // string// 输出解析文件的目录,url相对于html页面library: {type: "umd", // 通用模块定义// 导出库的类型name: "MyLibrary", // string | string[]// 导出库的名称},uniqueName: "my-application",// 此生成的唯一名称,以避免与同一HTML中的其他生成冲突name: "my-config",// 配置的名称,显示在输出中},module: {// 模块配置相关rules: [// 模块规则(配置loader、解析器选项){// 匹配的条件Conditions:test: /\.jsx?$/,include: [path.resolve(__dirname, "app")],exclude: [path.resolve(__dirname, "app/demo-files")]// 这些是匹配条件,每个条件接受一个正则表达式或字符串//测试和包含具有相同的行为,两者必须匹配//排除不能匹配(优先于测试和包含)//最佳做法://-仅在测试和文件名匹配中使用RegExp//-在include和exclude中使用绝对路径数组来匹配完整路径//-尽量避免排除,而更喜欢包含//每个条件还可以接收具有“and”、“or”或“not”属性的对象//这是一系列条件。issuer: /\.css$/,issuer: path.resolve(__dirname, "app"),issuer: { and: [ /\.css$/, path.resolve(__dirname, "app") ] },issuer: { or: [ /\.css$/, path.resolve(__dirname, "app") ] },issuer: { not: [ /\.css$/ ] },issuer: [ /\.css$/, path.resolve(__dirname, "app") ], // like "or"// 执行Actions:// 单个loader:loader: "babel-loader",// 应用的loader,相对于上下文解析// loader的配置选项options: {presets: ["es2015"]},// 应用多个复合loader和loader对应的optionsuse: ["htmllint-loader",{loader: "htmllint-loader",options: {//...}}],type: "javascript/auto",// 指定模块的类型},{oneOf: [// ...(rules)]// 只使用这一套规则},{// ... (conditions)rules: [// ...(rules)]// 使用所有这些嵌套规则(结合使用条件)}]},resolve: {// 用于解析模块请求的选项// 不适用于loader的模块解析modules: ["node_modules",path.resolve(__dirname, "app")],// 查找模块的目录(按数组顺序)extensions: [".js",".json",".jsx",".css"],// 使用的扩展名alias: {// 模块名称别名的列表// 别名是相对于当前上下文导入的"module": "new-module",// 别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file""only-module$": "new-module",// 别名 "only-module" -> "new-module",但不匹配 "only-module/path/file" -> "new-module/path/file""module": path.resolve(__dirname, "app/third/module.js"),// 别名“module”->“/app/third/module.js”和“module/file”导致错误"module": path.resolve(__dirname, "app/third"),// 别名为“module”->”/app/third“和“module/file”->”/app/third/file”[path.resolve(__dirname, "app/module.js")]: path.resolve(__dirname, "app/alternative-module.js"),// 别名“/app/module.js”->”/app/alternative module.js”}},performance: {}, // 用不上devtool: "source-map",// 通过为浏览器调试工具提供极其详细的源映射的元信息来增强调试能力// 但会牺牲构建速度!context: __dirname, // string(绝对路径!)// webpack的主目录// entry和module.rules.loader选项都相对于此目录解析target: 'web',// 由于 JavaScript 既可以编写服务端代码也可以编写浏览器代码,所以 webpack 提供了多种部署 target,web代表浏览器端,默认是browserlistdevServer: {proxy: {}, // 代理static: path.join(__dirname, 'public'), //boolean | string |  array | object, static file locationcompress: true, // 是否开启 gzip压缩historyApiFallback: true, // 不晓得咋用hot: true, // 热更新https: false,},plugins: [], //插件optimization: {// 优化选项chunkIds: "size",// 为模块生成ID的方法,告知 webpack 当选择模块 id 时需要使用哪种算法moduleIds: "size",// 模块ID的生成方法,告知 webpack 当选择模块 id 时需要使用哪种算法mangleExports: "size",// 将导出名称重命名为较短的名称minimize: true,// 最小化输出文件minimizer: [new CssMinimizer(), "..."],// 用于输出文件的最小值splitChunks: {cacheGroups: {"my-name": {// 定义具有特定属性的模块组test: /\.sass$/,type: "css/mini-extract"}}}}
}

二、导出方式

除了导出单个配置外,还有一些能满足更多需求的导出配置的方式。

a.导出为函数

区分开发环境和生产环境的情况,也可以由导出为函数来处理,这个函数包含两个参数:

  • 参数1是环境
  • 参数2是传递给webpack的配置项
module.exports = funtion(env, argv) {return {mode: env.production ? 'production':'development',devtool: env.production ? 'source-map' : 'eval',plugins: [new TerserPlugin({terserOptions: {compress: argv.mode === 'production'}})]}
}

b.导出为Promise

当需要异步加载配置变量时,webpack将执行函数并导出一个配置文件,同时返回一个Promise。webpack支持使用Promise.all([your promise]) 导出多个promise:

module.exports = () => {return new Promise((resolve, reject) => {setTimeout(() => {resolve({entry: './app.js',// ...})}, 5000)})
}

c.导出多种配置

除了导出单个配置对象/或函数,你可能也会需要导出多种配置(webpack@3以上)。当webpack运行时,所有配置项都会构建,比如对于多targets(如AMD和CommonJS)构建library时会非常有用:

module.exports = [{output: {filename: './dist-amd.js',libraryTarget: 'amd'},name: 'amd',entry: './app.js',mode: 'production'},{output: {filename: './dist-commonjs.js',libraryTarget: 'commonjs',},name: 'commonjs',entry: './app.js',mode: 'production'}
]

备注:如果你只传了一个--config-name名字标识,webpack将只会构建指定的配置项。

d.dependencies(基于c的基础上)

以防你的某个配置依赖于另一个配置的输出,你可以使用一个 dependencies 列表指定一个依赖列表:

module.exports = [{name: 'client',target: 'web',// …},{name: 'server',target: 'node',dependencies: ['client'],},
]

e.parallelism(基于c的基础上)

如果你导出了多个配置,你可以在配置中使用 parallelism 选项来指定编译的最大并发数。(webpack@5.22以上)

module.exports = [{//config-1},{//config-2},
];
module.exports.parallelism = 1;

三、使用其他语言

Webpack支持使用多种编程语言和数据描述格式来编写配置文件。在node-interpret中你可以找到当前所支持的文件类型列表,通过node-interpret,webpack能够处理这些类型的配置文件。

a.TypeScript

npm install --save-dev typescript ts-node @types/node @types/webpack// 如果使用webpack-dev-server,还需要安装以下依赖npm install --save-dev @types/webpack-dev-server

安装完成知乎便可以开始编写配置文件,示例如下:

// webpack.config.tsimport * as path from 'path';
import * as webpack from 'webpack';
// 如果需要配置devServer,需要引入以下内容
import 'webpack-dev-server'const config: webpack.Configuration = {mode: 'production',entry: './foo.js',output: {path: path.resolve(__dirname, 'dist'),filename: 'foo.bundle.js'}
}export default config;

该示例需要typescript版本在2.7及以上,并在tsconfig.json文件的compilerOptions中添加esModuleInterop和allowSyntheticDefaultImports两个配置项。

值得注意的是你需要确保tsconfig.json的compilerOptions中module选项的值为commonjs,否则webpack的运行会失败报错,因为ts-node不支持commonjs以外的其他模块规范。

你可以通过三个途径来完成module的设置:

  • 直接tsconfig.json文件
  • 修改tsconfig.json并且添加ts-node的设置
  • tsconfig-paths

第一种方法就是打开你的tsconfig.json文件,找到compilerOptions的配置,然后设置target和module的选项分别为“ES5”和“CommonJs”(在target设置为ES5时你也可以不显示编写module的配置)。

// tsconfig.json{"compilerOptions": {"target": "ES5","module": "ESNext"}
}

第二种方法就是添加ts-node设置:

你可以为tsc保持“module”:“ESNext”配置,如果你是用webpack或者其他构建工具的话,为ts-node设置一个重载(override):

// tsconfig.json{"compilerOptions": {"module": "ESNext",},"ts-node": {"compilerOptions": {"module": "CommonJS"}}
}

第三种方法需要先安装tsconfig-paths这个npm包,如下所示:

npm install --save-dev tsconfig-paths

安装后你可以为webpack配置创建一个单独的TypeScript配置文件,示例如下:

// tsconfig-for-webpack-config.json{"compilerOptions": {"module": "commonjs","target": "es5","esModuleInterop": true}
}

ts-node可以根据tsconfig-paths提供的环境变量process.env.TS_NODE_PROJECT来找到tsconfig.json文件路径。

process.env.TS_NODE_PROJECT变量的设置如下所示:

// package:json{"scripts": {"build": "cross-env TS_NODE_PROJECT=\"tsconfig-for-webpack-config.json\"webpack"}
}

之所以要添加cross-env,是因为我们在直接使用TS_NODE_PROJECT时遇到过“TS_NODE_PROJECT”unrecognized command报错的反馈,添加cross-env之后该问题也得到了解决。

b.CoffeeScript

与Typescript类似,在使用CoffeeScript前需要先安装其依赖,如下所示:

npm install --save-dev coffeescript

然后编写配置文件:

// webpack.config.coffeeHtmlWebpackPlugin = require('html-webpack-plugin')
webpack = require('webpack')
path = require('path')config = mode: 'production'entry: './path/to/my/entry/file.js'output: path: path.resolve(__dirname, 'dist')filename: 'my-first-bundle.js'module: rules: [{test: /\.(js|jsx)$/use: 'babel-loader'}]plugins: [new HtmlWebpackPlugin(template: './src/index.html')]module.exports = config

c.Babel and JSX

首先,跟上面两个方式一样,需要安装一些必要的依赖,如下所示:

npm install --save-dev babel-register jsxobj babel-preset-es2015

编写.babelrc配置文件:

{"presets": ["es2015"]
}

编写webpack配置文件:

// webpack.config.babel.jsimport jsxobj from 'jsxobj'// 插件引入示例
const CustomPlugin = (config) => ({...config,name: 'custom-plugin'
})export default (<webpack target="web" watch mode="production"><entry path="src/index.js" /><resolve><alias{...{react: 'preact-compat','react-dom': 'preact-compat'}}/></resolve><plugins><CustomPlugin foo="bar" /></plugins></webpack>
)

如果你在其他地方也使用了Babel并且modules的值设为false,则必须维护两份.babelrc的文件,或者你也可以将上述示例中的import jsxobj from 'jsxobj’替换为const jsxobj = require(‘jsxobj’)。并将新的export语法替换为module.exports,因为node还未支持ES6的模块语法。

四、注意事项

  1. webpack完全遵循CommonJS模块规范
  2. 可以通过require()引入其他文件
  3. 可以通过require()使用npm下载的工具函数
  4. 可以使用三元运算符来编写
  5. 可以对value使用常量或变量赋值
  6. 编写并执行函数,生成部分配置
  7. 配置文件不可过长,如有则需拆分多个,例如区分环境

本文就到此结束啦,感兴趣的小伙伴们就点点关注点点赞把~

重构Webpack系列之六 ---- 配置文件相关推荐

  1. 手写webpack系列一:了解认识loader-utils

    Created By JishuBao on 2019-03-29 12:38:22 Recently revised in 2019-04-01 12:38:22   欢迎大家来到技术宝的掘金世界, ...

  2. nginx系列之六:cache服务

    ** 前言 ** nginx系列之一:nginx入门 nginx系列之二:配置文件解读 nginx系列之三:日志配置 nginx系列之四:web服务器 nginx系列之五: 负载均衡 nginx系列之 ...

  3. java mysql jsp分页代码_JAVA/JSP学习系列之六(MySQL翻页例子)

    JAVA/JSP学习系列之六(MySQL翻页例子) 更新时间:2006年10月13日 00:00:00   作者: 一.运行前准备 下载了mysql的jdbc驱动(一个jar文件)并加载在CLASSP ...

  4. 带你深度解锁Webpack系列(优化篇)

    带你深度解锁Webpack系列(优化篇) 本文罗列出了十多种优化方式,大家可以结合自己的项目,选择适当的方式进行优化.这些 Webpack 插件的源码我大多也没有看过,主要是结合 Webpack 官方 ...

  5. HGE系列之六 管中窥豹(资源管理)

    HGE系列之六 管中窥豹(资源管理) 记的上次浮光掠影的讲了一些HGE中的基础类别,不知大家了解了多少,仔细看过的朋友肯定知道当时在讲述一个类别的构造函数时我打了个马虎,直接略过了,原因说的好像是比较 ...

  6. Webpack系列-第一篇基础杂记

    系列文章 Webpack系列-第一篇基础杂记 Webpack系列-第二篇插件机制杂记 Webpack系列-第三篇流程杂记 前言 公司的前端项目基本都是用Webpack来做工程化的,而Webpack虽然 ...

  7. Camera开发系列之六-使用mina框架实现视频推流

    章节 Camera开发系列之一-显示摄像头实时画面 Camera开发系列之二-相机预览数据回调 Camera开发系列之三-相机数据硬编码为h264 Camera开发系列之四-使用MediaMuxer封 ...

  8. 线程基础知识——Windows核心编程学习手札系列之六

    线程基础知识 --Windows核心编程学习手札系列之六 线程与进程一样由两部分构成:一是线程的内核对象,操作系统用它来对线程实施管理,也是系统用来存放线程统计信息的地方:二是线程堆栈,用于维护线程在 ...

  9. mongo 3.4分片集群系列之六:详解配置数据库

    这个系列大致想跟大家分享以下篇章: 1.mongo 3.4分片集群系列之一:浅谈分片集群 2.mongo 3.4分片集群系列之二:搭建分片集群--哈希分片 3.mongo 3.4分片集群系列之三:搭建 ...

  10. 《视频直播技术详解》系列之六:延迟优化

    七牛云于 6 月底发布了一个针对视频直播的实时流网络 LiveNet 和完整的直播云解决方案,很多开发者对这个网络和解决方案的细节和使用场景非常感兴趣. 结合七牛实时流网络 LiveNet 和直播云解 ...

最新文章

  1. python计算文件中字母出现次数_python – 计算文本文件中字母的频率
  2. 基于 CNN 特征区域进行目标检测
  3. 牛客网暑期ACM多校训练营(第六场)J Heritage of skywalkert
  4. html-webpack-plugin插件 根据模板生成多页面
  5. XML 序列化 【译】
  6. id nfc模拟_手机NFC也可以刷ID卡门禁?无聊测试居然成功了
  7. 视觉设计_视觉设计:
  8. 【每日一题】8月25日题目精讲 XOR-pyramid
  9. Vjios P1736 铺地毯【暴力,思维】
  10. 力扣-1508 子数组和排序后的区间和
  11. vi/vim 基本使用方法
  12. Dijkstra + 堆优化
  13. 实战项目-python库分析科比生涯数据
  14. 比特率(码率) = 采样率 (Sampling rate ) * 位深 (Bit depth)* 声道数目/Opus/AAC/mp3
  15. Jenkins邮件通知模板(Git修改版)
  16. 朴素贝叶斯算法,点进来了解了解。
  17. 修改windows系统网卡的MAC地址方法
  18. WordPress各种代码调用大全
  19. 【3D点云】PersFormer:基于透视Transformer的3D车道检测(ECCV2022)
  20. 好用的三维绘图软件CREO用来绘制圆角和倒角

热门文章

  1. 不装APP无法购物点餐开发票,这个“病”怎么治?
  2. 【扩频通信】基于matlab CDMA直接序列扩频系统仿真【含Matlab源码 1528期】
  3. 【水果识别】基于matlab GUI形态学水果大小识别【含Matlab源码 920期】
  4. 【通信】基于matlab FDTD法研究移动通信终端电磁辐射对人体的影响【含Matlab源码 761期】
  5. ios 持续获取定位 高德地图_高德地图API获取POI数据
  6. 传统量化与ai量化对比_量化AI偏差的风险
  7. ieee浮点数与常规浮点数_浮点数如何工作
  8. linux找不到mysql服务_linux mysql 找不到 mysql/mysql.h
  9. android 网络程序下载,Android从网络上下载文件
  10. 记Python的一些用法