【源码】vue-cli-dev

看见了

前言

学习vue-cli@3.0这个脚手架源码,希望达到以下目的:

  • 了解vue-cli的原理与机制
  • 学会编写命令行工具以及相关常用的npm包
  • 学会如何发布npm

准备

将GitHub上的仓库fork一份,再clone下来

@vue/babel-preset-app

这是所有Vue CLI项目中使用的默认Babel预设。(你可以简单认为是一系列 babel 的plugin组合)
  • babel.config.js
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ]
}

这里的@vue/cli-plugin-babel/preset入口就是@vue/babel-preset-app这个包。

入口index.js

// code snippet
module.exports = (context, options = {}) => {
  return {
    sourceType: "unambiguous", // 判断文件中是否出现了import/export,来决定采用的模块化标准
    overrides: [
      {
        exclude: [/@babel[/|\\\\]runtime/, /core-js/],
        presets,
        plugins,
      },
      {
        // there are some untranspiled code in @babel/runtime
        // https://github.com/babel/babel/issues/9903
        include: [/@babel[/|\\\\]runtime/],
        presets: [[require("@babel/preset-env"), envOptions]],
      },
    ],
  };
};

主要看overrides中第一个 option 对象。pluginspresets的执行顺序是plugins优先,所以先从plugins开始。

const plugins = [];
plugins.push([
  require("./polyfillsPlugin"),
  { polyfills, entryFiles, useAbsolutePath: !!absoluteRuntime },
]);

// 测试环境这里直接忽略
if (process.env.VUE_CLI_BABEL_TRANSPILE_MODULES) {
  envOptions.modules = "commonjs";
  if (process.env.VUE_CLI_BABEL_TARGET_NODE) {
    // necessary for dynamic import to work in tests
    plugins.push(require("babel-plugin-dynamic-import-node"));
  }
}

plugins.push(
  require("@babel/plugin-syntax-dynamic-import"),
  [
    require("@babel/plugin-proposal-decorators"),
    {
      decoratorsBeforeExport,
      legacy: decoratorsLegacy !== false,
    },
  ],
  [require("@babel/plugin-proposal-class-properties"), { loose }]
);

plugins.push([
  require("@babel/plugin-transform-runtime"),
  {
    regenerator: useBuiltIns !== "usage",

    // polyfills are injected by preset-env & polyfillsPlugin, so no need to add them again
    corejs: false,

    helpers: useBuiltIns === "usage",
    useESModules: !process.env.VUE_CLI_BABEL_TRANSPILE_MODULES,

    absoluteRuntime,

    version,
  },
]);

按照babel插件执行顺序,第一个是polyfillsPlugin.js.

// add polyfill imports to the first file encountered.
module.exports = (
  { types },
  { polyfills, entryFiles = [], useAbsolutePath }
) => {
  return {
    name: 'vue-cli-inject-polyfills',
    visitor: {
      Program (path, state) {
        if (!entryFiles.includes(state.filename)) {
          return
        }

        // imports are injected in reverse order
        polyfills
          .slice()
          .reverse()
          .forEach(p => {
            createImport(path, p, useAbsolutePath)
          })
      }
    }
  }
}

@vue/cli-overlay

定制覆盖Client

在TODO列表中,还没实现

@vue/cli-plugin-babel

@vue/cli-plugin-webpack-4

阅读 212
219 声望
2 粉丝
0 条评论
你知道吗?

219 声望
2 粉丝
宣传栏