webpack-chain源码 vue-cli配置webpack

栏目: JavaScript · 发布时间: 4年前

内容简介:需要先预习 下列方法如果对这些知识生疏,点此学习 (

github.com/neutrinojs/…

git clone   https://github.com/neutrinojs/webpack-chain.git
复制代码

知识准备

需要先预习 下列方法

ES6 Set
ES6 Map
ES6 Class
includes reduce map forEach
Object.keys Object.assign
...

如果对这些知识生疏,点此学习 ( es6.ruanyifeng.com/#docs/class ) 把这些掌握后,阅读很easy

目录结构

目标是把src 里面的方法都了解会用

└── webpack-chain
    ├── src
    │   ├── Chainable.js
    │   ├── ChainedMap.js
    │   ├── ChainedSet.js
    │   ├── Config.js
    │   ├── DevServer.js
    │   ├── Module.js
    │   ├── Optimization.js
    │   ├── Orderable.js
    │   ├── Output.js
    │   ├── Performance.js
    │   ├── Plugin.js
    │   ├── Resolve.js
    │   ├── ResolveLoader.js
    │   ├── Rule.js
    │   └── Use.js
复制代码

文件名全是首字母大写,从命名看,每个里面全是类的定义,用 extends 来实现继承

Chainable ChainedMap.js ChainedSet.js

ChainedMap.js ChainedSet.js 都继承了 Chainable

Chainable 以able 为后缀表示具有什么能力。这个库维护了 parent ,用end来实现链式。很像jq的end().

ChainedMap.js ChainedSet.js 这两个里面分别包装了 js 原生的 Map, Set 结构。

ChainedMap

// 维护了parent 链,由上文提到的`Chainable`来做的
// 实例化了一个store (仓库) 拥有Map结构的方法
 constructor(parent) {
    super(parent);
    this.store = new Map();
  }

// 从 Map 移除所有 配置.
clear()

// 通过键值从 Map 移除单个配置.
// key: *
delete(key)

// 获取 Map 中相应键的值
// key: *
// returns: value
get(key)

// 都是map的原生方法封装
has(key) + set(key, value)

// 传入key 和 函数两个参数
当拥有key的时候 返回获取到的值
如果key 没有定义过,调用函数生成键值对
 getOrCompute(key, fn) {
    if (!this.has(key)) {
      this.set(key, fn());
    }
    return this.get(key);
  }



把对象进行清洗,传参数{a:undefined,
               b: [],
               c:{},
               d:0
             }
 输出{ d: 0 },会把undefined,[],{}这些过滤掉。
clean(obj)


// when的用法
// when 有断言作用,第2,3参数是函数。函数参数就是this。
// config
//  .when(process.env.NODE_ENV === 'production',
//      config => config.plugin('minify').use(BabiliWebpackPlugin),
//       config => config.devtool('source-map')
//  );
 when(
    condition,
    whenTruthy = Function.prototype,
    whenFalsy = Function.prototype
  ) {
    if (condition) {
      whenTruthy(this);
    } else {
      whenFalsy(this);
    }

    return this;
  }


extend 参数是数组,会批量往this上绑定一些方法,
绑定方法是用的set,说明再次调用会覆盖掉上次。
例如: this.extend(['watch'])
会生成 this.watch = value => this.set(method, value);

复制代码

理解了ChainedMap,那ChainedSet也容易

实战配置vue-cli 项目

用vue-cli3生成项目后

vue inspect > default.json
复制代码

会生成默配置到default.json

这些配置是从这个包 node_modules/@vue/cli-service/lib/config/base.js 生成的

打开这个文件看一下webpack-chain的用法.

vue引入webpack-chain的文件是 node_modules/@vue/cli-service/lib/Service.js

在此文章搜索下面三行

const Config = require('webpack-chain')  // 会引入webpack-chain库"src/Config.js"文件

// 只实例化一次,chainWebpack 的config参数就是这个实例
const chainableConfig = new Config()

// 会生成配置
let config = chainableConfig.toConfig()

复制代码

我们看一下 webpack-chain 源码 Config.js 文件

toConfig() {

    //  入口entry
    const entryPoints = this.entryPoints.entries() || {};

    // clean 方法上文Map结构有讲
    return this.clean(

        // this.entries()  全部this.store的值。包含this.extend()方法生成的速记方法
      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.toConfig(),
        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() }),
          {}
        ),
      })
    );
  }
复制代码

修改 entry

chainWebpack: config => {
  config.entryPoints.clear() // 会把默认的入口清空
  config.entry('main').add('./src/main.js')
  config.entry('routes').add('./src/app-routes.js')
}


链式调用:end方法
clear方法会把vue-cli默认的.entry('app')清空。可以在同一个chunk,add多个模块。
config.entryPoints.clear().end()
    .entry('main').add('./src/main.js').end()
    .entry('routes').add('./src/app-routes.js')
复制代码

vue inspect > entry.json 对比entry.json和default.json的entry字段,成功修改。

  • 速记方法 看上文Map extend 介绍

用速记方法修改简单的字段

config.mode('production')
    config.watch(true)

    生成文件,查看已变成
     mode: 'production',
     watch: true,

复制代码

用速记方法修改proxy

chainWebpack: config => {
    config.devServer.port(9898)
      .open(true)
      .proxy({'/dev': {
                 target: 'http://123.57.153.106:8080/',
                 changeOrigin: true,
                 pathRewrite: {
                   '^/dev': ''
                 }
               }
           })
  }

复制代码

用速记方法修改output

chainWebpack: config => {
   config
      .when(process.env.NODE_ENV === 'production', config => {
        config.output.publicPath('//busi.cdnimg.com/demo-finance/dist/')
      });
  }

复制代码

添加7牛plugin

const QiniuPlugin = require('qn-webpack')

  chainWebpack: config => {
     config.plugin('7niu')
              .use(QiniuPlugin,[{
                accessKey: '1234567654356',
                secretKey: '2344344545',
                bucket: 'busi-cdn',
                path: 'cdn-finance/dist/',
                exclude: /index\.html$/ // 排除特定文件,正则表达式
              }]);
  }


通过阅读Plugin.js源码toConfig方法,发现还可以传字符串类型,还有对象实例
const init = this.get('init'); // 会调用init(plugin, args); 把插件函数和参数传入
let plugin = this.get('plugin'); // 获取plugin
const args = this.get('args');// 获取参数


config
          .plugin('7niu')
          .use('qn-webpack',[{
            accessKey: '1234567654356',
            secretKey: '2344344545',
            bucket: 'busi-cdn',
            path: 'cdn-finance/dist/',
            exclude: /index\.html$/ // 排除特定文件,正则表达式
          }]);


生成的效果
 /* config.plugin('7niu') */
    new (require('qn-webpack'))(
      {
        accessKey: '1234567654356',
        secretKey: '2344344545',
        bucket: 'busi-cdn',
        path: 'cdn-finance/dist/',
        exclude: /index\.html$/
      }
    )
复制代码

添加clear plugin

用对象实例的方式

const CleanPlugin = require("clean-webpack-plugin");

const clean  = new CleanPlugin()

    config
      .plugin('clean').use(clean)
复制代码

添加 删除loader

把vue的loader 都删掉

config.module
      .rule('vue').uses.clear()

复制代码

添加loader 从 @vue/cli-service/lib/config/base.js 的一段代码来参考

webpackConfig.module
      .rule('images')
        .test(/\.(png|jpe?g|gif|webp)(\?.*)?$/)
        .use('url-loader')
          .loader('url-loader')
          .options(genUrlLoaderOptions('img'))
复制代码

单独调试

const Config = require('webpack-chain');

const config = new Config();

const CleanPlugin = require("clean-webpack-plugin");
config
  .plugin('clean')
  .use(CleanPlugin);

let r = config.toConfig()
console.log(r)
复制代码

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

嵌入式系统开发之道

嵌入式系统开发之道

2011-12 / 69.00元

《嵌入式系统开发之道:菜鸟成长日志与项目经理的私房菜》用平易朴实的语言,以一个完整的嵌入式系统的开发流程为架构,通过一位“菜鸟”工程师与项目经理的诙谐对话,故事性地带出嵌入式系统概念及开发要素,并点出要成为一名称职的嵌入式系统工程师,在实际工作中所必须具备的各项知识及技能。 《嵌入式系统开发之道:菜鸟成长日志与项目经理的私房菜》可以分为三大部分:第1、3、4、17、18、19章和附录D为嵌入......一起来看看 《嵌入式系统开发之道》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器