1

@vue/cli-plugin-babel/index.js 中:

api.genCacheConfig('babel-loader', {}, [])

我们看一下 api.genCacheConfig 在文件:@vue/cli-service/lib/PluginAPI.js 中被定义:

Generate a cache identifier from a number of variables

在函数一开始接受 3 个参数:

  • id
  • partialIdentifier
  • configFiles

然后看一下函数的内部:

返回:

  • cacheIdentifier
  • cacheDirectory
genCacheConfig (id, partialIdentifier, configFiles) {
  const cacheDirectory = this.resolve(`node_modules/.cache/${id}`)
  const variables = {}
  const cacheIdentifier = hash(variables)
  return { cacheDirectory, cacheIdentifier }
}

我们打印了 cacheDirectory 目录,发现一个目录地址:

/Users/***/node_modules/.cache

我本地的有 4 个文件夹:

  • babel-loader
  • uglifyjs-webpack-plugin
  • eslint-loader
  • vue-loader

我们上面 cli-plugin-babel 就是指向了 babel-loader 的目录:

上面的 hash 用到了:

const hash = require('hash-sum')
/Users/***/node_modules/.cache/babel-loader

首先,babel-loader 是不具备去一个 .cache 目录写入文件的,那到底是谁呢?

还记得我们之前通过 vue inspect --rule js 打印的 babelwebpack 配置吗?

/* config.module.rule('js') */
{
  test: /\.jsx?$/,
  exclude: [
    function () { /* omitted long function */ }
  ],
  use: [
    /* config.module.rule('js').use('cache-loader') */
    {
      loader: 'cache-loader',
      options: {
        cacheDirectory: '/Users/***/node_modules/.cache/babel-loader',
        cacheIdentifier: '2f4347b9'
      }
    },
    /* config.module.rule('js').use('babel-loader') */
    {
      loader: 'babel-loader'
    }
  ]
}

这里面的 use 配置在 babel-loader 之前配置了一个 cache-loader

{
  loader: 'cache-loader',
  options: {
    cacheDirectory: '/Users/***/node_modules/.cache/babel-loader',
    cacheIdentifier: '2f4347b9'
  }
}

cache-loader 到底做什么的呢:

Caches the result of following loaders on disk (default) or in the database

它的使用中有一个示例:

Add this loader in front of other (expensive) loaders to cache the result on disk.

一般它会放置在 use 配置里面,而且是其他 loaders 的前面:

module.exports = {
  module: {
    rules: [
      {
        test: /\.ext$/,
        use: [
          'cache-loader',
          ...loaders
        ],
        include: path.resolve('src')
      }
    ]
  }
}

那其实结果就很清晰了,写文件的就是它:

一开始通过 Set 来创建一个对象,后面还使用了 addhas
var directories = new Set();

它有一个函数 write,接受 3 个参数:

  • key
  • data
  • callback
function write(key, data, callback) {
  var dirname = path.dirname(key);
  var content = JSON.stringify(data);

  if (directories.has(dirname)) {
    // for performance skip creating directory
    fs.writeFile(key, content, 'utf-8', callback);
  } else {
    mkdirp(dirname, function (mkdirErr) {
      if (mkdirErr) {
        callback(mkdirErr);
        return;
      }

      directories.add(dirname);

      fs.writeFile(key, content, 'utf-8', callback);
    });
  }
}

这里创建目录用到了:mkdirp 来创建目录

var mkdirp = require('mkdirp');

然后通过 fs.writeFile 来写文件

var fs = require('fs');
fs.writeFile(key, content, 'utf-8', callback);

dailyvuejs
1.6k 声望307 粉丝

目前专注 Vue CLI 3 源码和 vue.config.js 配置内部设计等学习分享