webpack(9) 配置文件
一. 经过我实践证明: webpack的配置最好采用以下:
配置文件返回一个函数, 而该函数满足以下两个条件:
- 包含一个参数, 该参数作为命令行参数的传递对象, 能够为不同配置灵活配置;
- 并且返回一个配置对象;
运行: npx webpack --env prod 则会是生成环境,
运行: npx webpack 则是开发环境
//webpack.config.js默认配置文件(dev) const path = require("path"); const MyPlugin = require("./src/plugin/Myplugin"); const FileListPlugin = require("./src/plugin/FileListPlugin"); module.exports = function (env) { return { mode: env.prod ? 'production' : 'development', devtool: env.prod ? 'source-map' : 'eval', plugins: [ new MyPlugin(), new FileListPlugin("myfile") ], module: { rules: [ { test: /\.css$/, use: ["./src/myloader/mycssloader"] }, { test: /\.(png|jpg|gif|webp|jpeg)$/i, use: [{ loader: "./src/myloader/myimgloader", options: { limit: 900, } }] }, { test: /\.js$/,//匹配规则 use: [ //用什么处理, 可以写多个loader // { loader: "./src/myloader/myloader.js" }, //loader的路径 { loader: "./src/myloader/myloader2.js", options: { changevalue: "我的吧" } } // {loader:"./src/myloader/myloader2.js?changevalue=我的吧"} ], } ] }, entry: { index: "./src/index.js" }, output: { // filename: "[name].[chunkhash:5].js", filename: "[name].js", path: path.resolve("./", "output") } } }
二: webpack配置文件中的几个点,
1.context: path.resolve(__dirname,"src") 将入口文件和loader的相对路径,改为context的值. 这种看似灵活的配置, 其实是加大了webpack的难度, 所以, 被vue抛弃.
影响的是entry和loader的相对路径, 这两个的路径配置以context作为参照物
2. output中的library和libraryTarget:
library: 作用是将打包结果暴露给一个变量,
libraryTarget的作用是如何导出, 默认值是var. 也可以定义为window
在引入打包文件后, 可以获取library变量定义的值来用, 比如jquery中的$
output: { // filename: "[name].[chunkhash:5].js", library: "$", libraryTarget:"window",
3. target: 值是"web"或者"node"
target 设置为 node
,webpack 将在Node.js 环境编译代码。如果值为"web", 将在web环境中编译. 影响就是, webpack的编译过程中, 如果碰到像导入fs模块时候, 如果是在node环境, 是可以的,webpack会在依赖分析时候, 计入fs并导入,
如果在web环境中, 是错误的, 因为require("fs")在编译开始就会当做引入依赖的语句, 被立刻替换, 在替换过程中,如果发现fs是web环境, 则会寻找nodemodules的fs模块, web的依赖没有该模块. 会报错
在require("fs")时。
4.noParser: 防止 webpack 解析那些与给定正则表达式相匹配的文件。通常用于忽略jquery或者lodash等常用的大型模块.
不会对模块做任何解析, 直接在读取文件后保存代码. 不会进行语法树分析, 并将该模块内的依赖作chunk的模块记录;
影响的只是打包性能, 与运行性能无关, 所以对性能优化没有任何作用
忽略的文件中 不应该含有 import
, require
, define
的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。
module.exports = { //... module: { noParse: /jquery|lodash/, }, };
5. resolve(解析): 这些选项能设置模块如何被解析
//index.js if(Math.random() > 0.5){ require("./a"); }
webpack经过编译后, 生成的打包文件中肯定包含a.js. 无论Math.random()的值是多少. 因webpack在读取index.js后, 会进行语法树分析, 查找到所有引入语句, 然后进行递归引入.详情见上图.
5.1 resolve.modules: 告诉 webpack 解析模块时应该搜索的目录。就是查找的模块在哪个目录下, 默认是"node_modules";
我改成aaa.打包立刻报错, 因为去require(不加./或者../)的模块, 它就去aaa目录找, 没有aaa目录
5.2 resolve.extensions
: 省略的后缀名,默认值是[".js", ".json"]
我们在代码中写var a = require("./a"), 参数不需要写a.js就是因为有resolve.extentions,根据值逐个匹配. webpack会先找同级目录下的a.js,如果没有找a.json
.vue 等都是通过该配置实现的.
5.3 resolve.alias: 创建 import
或 require
的别名,来确保模块引入变得更简单
import
或 require
的别名,来确保模块引入变得更简单
const path = require('path'); module.exports = { //... resolve: { alias: { "@": path.resolve(__dirname, 'src'),//必须是绝对路径 Templates: path.resolve(__dirname, 'src/templates/'), }, }, };
@是绝对路径, 所以不需要"./@/a.js"
6 externals(外部扩展): 防止将某些 import
的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies), 在打包后的代码中不需要将外部引入的代码打包进来, 减小代码体积。
如:在页面中已经用cdn引入了jquery后, 不需要再webpack中下载jquery的情况下, 直接用外部扩展
module.exports = { //... externals: { jquery: 'jQuery',
lodash: "_" }, }
然后可以直接在文件中运行下面的代码:
import $ from 'jquery';
import _ from "lodash";
在打包后的代码中, 可以看到lodash只是用了一句话引入了;因为已经在页面中引入了lodash, 在全局中已经有变量_了,直接可用require导入