内容简介:在我们讲到vue cli3中在commands文件夹里面的是调用api.registerCommand方法,在config文件夹里面的(teserOptions.js和html除外)是调用api.chainWebpack方法,该方法会将传得的参数(该参数是一个方法)push到this.service.webpackChainFns数组。今天就展开看看里面具体是什么。
在我们讲到 从vuecli3学习webpack记录(一)vue-cli-serve机制
vue cli3中在commands文件夹里面的是调用api.registerCommand方法,在config文件夹里面的(teserOptions.js和html除外)是调用api.chainWebpack方法,该方法会将传得的参数(该参数是一个方法)push到this.service.webpackChainFns数组。
今天就展开看看里面具体是什么。
1.this.service其实就是cli3里面的Service(node_modules/@vue/cli-service/lib/Service.js)的实例,通过api.registerCommand方法将对应的serve(就是npm run serve那个serve)等command加入到this.commands这个对象属性里面,通过api.chainWebpack方法将app、base等webpack配置加入到this.webpackChainFns这个数组属性里面。
2.上面的api其实是PluginApi(node_modules/@vue/cli-service/lib/PluginApi.js)的实例,
部分代码如下
// node_modules/@vue/cli-service/lib/PluginApi.js constructor (id, service) { this.id = id this.service = service } registerCommand (name, opts, fn) { if (typeof opts === 'function') { fn = opts opts = null } this.service.commands[name] = { fn, opts: opts || {}} } chainWebpack (fn) { this.service.webpackChainFns.push(fn) }
cli3帮我们配置的默认配置是怎么进去的呢?
在此之前,我们先看看这些配置长什么样吧,以node_modules/@vue/cli-service/lib/config/base.js为例
我们一般在webpack里面是这样配置它
module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig } ] }
而在cli3里面这样配置
module.exports = (api, options) => { api.chainWebpack(webpackConfig => { webpackConfig.module .rule('vue') .test(/\.vue$/) .use('cache-loader') .loader('cache-loader') .options(vueLoaderCacheConfig) .end() .use('vue-loader') .loader('vue-loader') .options(Object.assign({ compilerOptions: { preserveWhitespace: false } }, vueLoaderCacheConfig)) webpackConfig .plugin('vue-loader') .use(require('vue-loader/lib/plugin')) webpackConfig.module .rule('images') .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/) .use('url-loader') .loader('url-loader') .options(genUrlLoaderOptions('img')) }) }
可以看出webpack的配置可以以链式调用的方式添加,这样就可以以更加灵活的函数式添加配置了。
webpackConfig
是什么鬼,这就要再次回到Service.js了,看它是怎执行 webpackChainFns
数组里面的函数了
const Config = require('webpack-chain') resolveChainableWebpackConfig () { const chainableConfig = new Config() // apply chains this.webpackChainFns.forEach(fn => fn(chainableConfig)) return chainableConfig }
再看看 webpack-chain
const ChainedMap = require('./ChainedMap'); const ChainedSet = require('./ChainedSet'); const Resolve = require('./Resolve'); const ResolveLoader = require('./ResolveLoader'); const Output = require('./Output'); const DevServer = require('./DevServer'); const Plugin = require('./Plugin'); const Module = require('./Module'); const Optimization = require('./Optimization'); const Performance = require('./Performance'); module.exports = class extends ChainedMap { constructor() { super(); this.devServer = new DevServer(this); this.entryPoints = new ChainedMap(this); this.module = new Module(this); this.node = new ChainedMap(this); this.optimization = new Optimization(this); this.output = new Output(this); this.performance = new Performance(this); this.plugins = new ChainedMap(this); this.resolve = new Resolve(this); this.resolveLoader = new ResolveLoader(this); this.extend([ 'amd', 'bail', 'cache', 'context', 'devtool', 'externals', 'loader', 'mode', 'parallelism', 'profile', 'recordsInputPath', 'recordsPath', 'recordsOutputPath', 'stats', 'target', 'watch', 'watchOptions', ]); } toConfig() { const entryPoints = this.entryPoints.entries() || {}; return this.clean( Object.assign(this.entries() || {}, { node: this.node.entries(), output: this.output.entries(), resolve: this.resolve.toConfig(), resolveLoader: this.resolveLoader.toConfig(), devServer: this.devServer.toConfig(), module: this.module.toConfig(), optimization: this.optimization.entries(), plugins: this.plugins.values().map(plugin => plugin.toConfig()), performance: this.performance.entries(), entry: Object.keys(entryPoints).reduce( (acc, key) => Object.assign(acc, { [key]: entryPoints[key].values() }), {} ), }) ); } }
原来它针对webpack的配置里面的每一个大项都设置了不同的属性,并且分配以不同的方式实现。我们还可以看到里面有个 toConfig
方法,它会将最终的配置返回为我们熟悉的对象形式 的wepback配置,毕竟webpack只认这种配置。
下面就以 this.module
为例吧,因为看到它的链式调用里面有个 end
方法,会让链式调用调回去,方便执行后续的 use('vue-loader')
// node_modules/webpack-chain/src/Module.js module.exports = class extends ChainedMap { constructor(parent) { super(parent); this.rules = new ChainedMap(this); this.defaultRules = new ChainedMap(this); this.extend(['noParse']); } }
Module
继承 ChainMap
,而 ChainMap
又继承自 Chainable
,我们要看的 end
方法就是在这里
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script> <script> (adsbygoogle = window.adsbygoogle || []).push({ google_ad_client: "ca-pub-3013839362871866", enable_page_level_ads: true }); </script>
// node_modules/webpack-chain/src/Chainable.js module.exports = class { constructor(parent) { this.parent = parent; } batch(handler) { handler(this); return this; } end() { return this.parent; } };
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- springboot 默认日志配置
- [Framework]设置默认WiFi配置
- SpringBoot 实战 (七) | 默认日志配置
- 「快学SpringBoot」配置文件的加载顺序和配置项默认值设置
- Struts2中配置默认Action
- RabbitMQ默认集群模式搭建配置实现步骤
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JavaScript高级程序设计(第3版)
[美] Nicholas C. Zakas / 李松峰、曹力 / 人民邮电出版社 / 2012-3-29 / 99.00元
本书是JavaScript 超级畅销书的最新版。ECMAScript 5 和HTML5 在标准之争中双双胜出,使大量专有实现和客户端扩展正式进入规范,同时也为JavaScript 增添了很多适应未来发展的新特性。本书这一版除增加5 章全新内容外,其他章节也有较大幅度的增补和修订,新内容篇幅约占三分之一。全书从JavaScript 语言实现的各个组成部分——语言核心、DOM、BOM、事件模型讲起,深......一起来看看 《JavaScript高级程序设计(第3版)》 这本书的介绍吧!