温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何配置Webpack

发布时间:2021-10-14 11:34:30 来源:亿速云 阅读:133 作者:iii 栏目:开发技术

本篇内容主要讲解“如何配置Webpack”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何配置Webpack”吧!

为什么出现 webpack-chain  ?

相信大家都对业界鼎鼎有名的构建工具Webpack并不陌生了,作为目前为止最稳定、生产环境应用最多的构建打包工具,它固然有着很多优势,比如:

  • 生态丰富。在社区有大量的 loader 和 plugin,想要的基本都能找到。

  • 可插拔的插件机制。基于 Tapable 实现的可扩展架构。

  • 文档成熟。有中文版,且一直在更新和维护。

  • 稳定性高。现在正式的前端项目生产环境下基本用 Webpack 来构建,经过这么多年业界的验证,该踩的坑也都踩的差不多了。

但其实说了这么多优势,大家估计还是对这个东西没什么好感,因为还有最重要的一点不容忽视,那就是开发体验。对于构建打包这个事情来说,本来就是工程化当中的一个细节极其复杂的环节,需要输入大量的配置信息来保证打包结果符合预期。在Webpack当中,我们如果不用其他的方案,就只有手动地配置一个巨大的  JavaScript 对象,所有的配置信息都在这个对象当中,这样原始的方式的确给人体验很不好,归纳为以下几个原因:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 对象过于庞大,直观上让人看的眼花缭乱,尽管可以封装一些逻辑,但还是避免不了深层的嵌套配置;

  3. 难以动态修改。举个例子,如果通过脚本动态修改一些配置信息,比如删除 babel-loader 的一个  plugin,那么需要从最顶层的配置对象,一步步找到到 babel-loader 的位置,然后遍历插件列表,这个手动寻找和遍历的过程比较繁琐。

  4. 难以共享配置。如果你尝试跨项目共享 webpack 配置对象,那后续的修改就会变的混乱不堪,因为你需要动态地修改原来的配置。

社区当中也有人发现了这些痛点,于是出现了针对Webpack的流式配置方案——webpack-chain。

webpack-chain 核心概念

其实真正学会  webpack-chain,我觉得首先不是去学习具体每个属性的配置方法,而是理解webpack-chain核心的两个对象——ChainedMap和ChainedSet。

什么是 ChainMap ?

比如我现在配置路径别名:

config.resolve.alias   .set(key, value)   .set(key, value)   .delete(key)   .clear()

那么,现在的 alis  对象就是一个ChainMap。如果一个属性在webpack-chain当中标记为ChainMap之后,它会有一些额外的方法,并且允许这些链式调用(如上面的示例)。

接下来就来一个个认识这些方法:

// 清空当前 Map 的所有属性 clear() // 通过键值从 Map 移除单个配置. delete(key) // Map中是否存在一个配置值的特定键,返回真或假 has(key) // 返回 Map中已存储的所有值的数组 values() //  提供一个对象,这个对象的属性和值将映射进 Map。第二个参数为一个数组,表示忽略哪些属性 merge(obj, omit) // handler: ChainedMap => ChainedMap // 一个把ChainedMap实例作为单个参数的函数 batch(handler) // condition: Boolean // whenTruthy: ChainMap -> any, 条件为真时执行 // whenFalsy: ChainSet -> any, 条件为假时执行 when(condition, whenTruthy, whenFalsy) // 获取 Map 中相应键的值 get(key) // 先调用 get,如果找不到对应的值, 就返回 fn 函数返回的结果 getOrCompute(key, fn) // 配置键值对 set(key, value)

这些方法的返回对象也都是 ChainMap,这样可以实现链式调用,简化操作。在 Webpack中,大部分的对象都是  ChainMap,具体大家可以去源码当中看看,实现并不复杂。

ChainMap 是webpack-chain当中非常重要的一个数据结构,封装了链式调用的方法,以至于后面所有 ChainMap  类型的配置都可以直接复用ChainMap本身的这些方法,非常方便。

什么是 ChainSet ?

跟 ChainMap 类似,封装了自己的一套 API:

// 末尾增加一个值 add(value) // 在开始位置增加一个值 prepend(value) // 清空 set 内容 clear() // 删除某个值 delete(value) // 判断是否有某个值 has(value) // 返回值列表 values() // 合并给定的数组到 Set 尾部。 merge(arr) // handler: ChainSet => ChainSet // 一个把 ChainSet 实例作为单个参数的函数 batch(handler) // condition: Boolean // whenTruthy: ChainSet -> any, 条件为真时执行 // whenFalsy: ChainSet -> any, 条件为假时执行 when(condition, whenTruthy, whenFalsy)

ChainSet 的作用和ChainMap类似,也是封装了底层链式调用的  API,在需要操作Webpack配置当中的数组类型的属性时,通过调用ChainSet的方法即可完成。

速记方法

对于 ChainMap,有这样一种简化的写法,官网称之为速记写法:

devServer.hot(true);  // 上述方法等效于: devServer.set('hot', true);

因此,在实际的webpack-chain配置中,可以经常看到直接 .属性()这样调用方式,是不是感觉很巧妙?源码当中的实现非常简单:

extend(methods) {   this.shorthands = methods;   methods.forEach(method => {     this[method] = value => this.set(method, value);   });   return this; }

在ChainMap初始化的时候,会调用 extend 方法,然后把属性列表作为 methods参数直接传入,然后通过下面一行代码间接调用 set  方法:

this[method] = value => this.set(method, value);

这样的设计也是值得学习的。

配置 Webpack

首先,需要创建一个新的配置对象:

const Config = require('webpack-chain');  const config = new Config();  // 一系列链式操作之后 // 得到最后的 webpack 对象 console.log(config.toConfig())

然后依次配置 resolve、entry、output、module、plugins、optimization 对象,本文关键还是带大家能够落地  webpack-chain,因此详细介绍一下各个配置的使用方法。

entry 和 output

这里列举一个常用的配置,由于 Webpack 在 entry 和 output 挂了太多属性,大家参考 Webpack  官方文档照着如下的方式去配就好了。

config.entryPoints.clear() // 会把默认的入口清空 config.entry('entry1').add('./src/index1.tsx')//新增入口 config.entry('entry2').add('./src/index2.tsx')//新增入口  config.output       .path("dist")       .filename("[name].[chunkhash].js")       .chunkFilename("chunks/[name].[chunkhash].js")       .libraryTarget("umd")

alias

对于路径别名的配置,也是几乎所有项目必不可少的部分,配置方式如下:

// 可以发现 resolve.alias 其实是一个 ChainMap 对象 config.resolve.alias   .set('assets',resolve('src/assets'))   .set('components',resolve('src/components'))   .set('static',resolve('src/static'))   .delete('static') // 删掉指定的别名

plugins

插件的配置可以说是相当重要的一个环节了,webpack-chain 当中的配置会和平时的配置有些不同,让我们来具体看看。

1. 添加一个插件

// 先指定名字(这个名字是自定义的),然后通过 use 添加插件 config   .plugin(name)   .use(WebpackPlugin, args)

举个例子:

const ExtractTextPlugin = require('extract-text-webpack-plugin');  // 先指定名字(这个名字可以自定义),然后通过 use 添加插件,use 的第二个参数为插件参数,必须是一个数组,也可以不传 config.plugin('extract')   .use(ExtractTextPlugin, [{     filename: 'build.min.css',     allChunks: true,   }])

2. 移除插件

移除一个插件很简单,还记得添加插件时我们指定了每个插件的 name 吗?现在通过这个 name 移除即可:

config.plugins.delete('extract')

3. 指定插件在 xx 插件之前/之后调用

比如,我现在需要指定 html-webpack-plugin 这个插件在刚刚写的 extract 插件之前执行,那么这么写就行了:

const htmlWebpackPlugin = require('html-webpack-plugin');  config.plugin('html')   .use(htmlWebpackPlugin)   .before('extract')

通过 before 方法,传入另一个插件的 name 即可,表示在另一个插件之前执行。

同样,如果需要在 extract 插件之后执行,调用 after 方法:

config.plugin('html')   .use(htmlWebpackPlugin)   .after('extract')

4. 动态修改插件参数

我们也可以用 webpack-chain 来动态修改插件的传参,举个例子:

// 使用 tap 方法修改参数 config   .plugin(name)   .tap(args => newArgs)

5. 修改插件初始化过程

我们也可以自定义插件的实例化的过程,比如下面这样:

// 通过 init 方法,返回一个实例,这将代替原有的实例化过程 config   .plugin(name)   .init((Plugin, args) => new Plugin(...args));

loader

loader 是 Webpack 中必不可少的一个配置,下面我们来看看 loader 的相关操作。

1. 添加一个 loader

config.module   .rule(name)     .use(name)       .loader(loader)       .options(options)

举个例子:

config.module   .rule('ts')   .test(/\.tsx?/)   .use('ts-loader')     .loader('ts-loader')     .options({       transpileOnly: true     })     .end()

2. 修改 loader 参数

可通过 tap 方法修改 loader 的参数:

config.module   .rule('ts')   .test(/\.tsx?/)   .use('ts-loader')     .loader('ts-loader')     .tap(option => {       // 一系列       return options;     })     .end()

在所有的配置完成之后,可以通过调用config.toConfig()来拿到最后的配置对象,可以直接作为webpack的配置。

3. 移除一个 loader

// 通过 uses 对象的 delete 方法,根据 loader 的 name 删除 config.module   .rule('ts')   .test(/\.tsx?/)   .uses.delete('ts-loader')

optimization

Webpack  中的optimization也是一个比较庞大的对象,参照官方文档:https://webpack.js.org/configuration/optimization/。

这里以其中的 splitChunks 和 minimizer 为例来配置一下:

config.optimization.splitChunks({      chunks: "async",      minChunks: 1, // 最小 chunk ,默认1      maxAsyncRequests: 5, // 最大异步请求数, 默认5      maxInitialRequests : 3, // 最大初始化请求数,默认3      cacheGroups:{ // 这里开始设置缓存的 chunks          priority: 0, // 缓存组优先级          vendor: { // key 为entry中定义的 入口名称              chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async)              test: /react|vue/, // 正则规则验证,如果符合就提取 chunk              name: "vendor", // 要缓存的 分隔出来的 chunk 名称              minSize: 30000,              minChunks: 1,          }      } });  // 添加一个 minimizer config.optimization   .minimizer('css')   .use(OptimizeCSSAssetsPlugin, [{ cssProcessorOptions: {} }]) // 移除 minimizer config.optimization.minimizers.delete('css') // 修改 minimizer 插件参数 config.optimization   .minimizer('css')   .tap(args => [...args, { cssProcessorOptions: { safe: false } }])

善用条件

配置之前提到过,对于ChainSet和ChainMap对象都有条件配置方法when,可以在某些很多场景下取代  if-else,保持配置的链式调用,让代码更加优雅。

config.when(   process.env.NODE === 'production',   config.plugin('size').use(SizeLimitPlugin) )

到此,相信大家对“如何配置Webpack”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI