webpack-chain源码 vue-cli配置webpack

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

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

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)
复制代码

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

查看所有标签

猜你喜欢:

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

Concepts, Techniques, and Models of Computer Programming

Concepts, Techniques, and Models of Computer Programming

Peter Van Roy、Seif Haridi / The MIT Press / 2004-2-20 / USD 78.00

This innovative text presents computer programming as a unified discipline in a way that is both practical and scientifically sound. The book focuses on techniques of lasting value and explains them p......一起来看看 《Concepts, Techniques, and Models of Computer Programming》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

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

Markdown 在线编辑器