Open wuxianqiang opened 3 years ago
loadModule 源码
exports.loadModule = function (request, context, force = false) {
// createRequire doesn't work with jest mocked fs
// (which we used in tests for cli-service)
if (process.env.VUE_CLI_TEST && context === '/') {
return require(request)
}
try {
return createRequire(path.resolve(context, 'package.json'))(request)
} catch (e) {
const resolvedPath = exports.resolveModule(request, context)
if (resolvedPath) {
if (force) {
clearRequireCache(resolvedPath)
}
return require(resolvedPath)
}
}
}
const createRequire = Module.createRequire || Module.createRequireFromPath || function (filename) {
const mod = new Module(filename, null)
mod.filename = filename
mod.paths = Module._nodeModulePaths(path.dirname(filename))
mod._compile(`module.exports = require;`, filename)
return mod.exports
}
request 是 @vue/cli-service/generator,context 是输出目录,已 context 为出发点找 @vue/cli-service/generator
Module.createRequire(path.resolve(context, 'package.json'))(request)
目的就是为了改变加载的位置,要从 context 这个输出目录里面加载,不能直接写 require 为当前目录
核心属性
pkg 表示 package.json
plugins 表示 [{id, apply, options}]
files 表示 {文件名: 文件内容}
fileMiddlewares
rootOptions 其实就是 @vue/cli-service的options
// // pligins = [{id: @vue/cli-plugin-babel, apply: @vue/cli-plugin-babel/generator等等插件导出的函数,options: {参数}}]
module.exports = class Generator {
constructor (context, {
pkg = {}, // 存放 package.json
plugins = [], // 存放之前构造的插件
afterInvokeCbs = [],
afterAnyInvokeCbs = [],
files = {}, // 存放 文件名:文件内容,这里放最后生成的所有内容
invoking = false
} = {}) {
this.context = context
this.plugins = sortPlugins(plugins)
this.originalPkg = pkg
this.pkg = Object.assign({}, pkg) // 注意这里 package.json
this.pm = new PackageManager({ context })
this.imports = {}
this.rootOptions = {}
this.afterInvokeCbs = afterInvokeCbs
this.afterAnyInvokeCbs = afterAnyInvokeCbs
this.configTransforms = {}
this.defaultConfigTransforms = defaultConfigTransforms
this.reservedConfigTransforms = reservedConfigTransforms
this.invoking = invoking
// for conflict resolution
this.depSources = {}
// virtual file tree
this.files = Object.keys(files).length // 注意这里 {文件名: 文件内容}
// when execute `vue add/invoke`, only created/modified files are written to disk
? watchFiles(files, this.filesModifyRecord = new Set())
// all files need to be written to disk
: files
this.fileMiddlewares = [] // 这里是核心,每个插件都会往中间件里面插入中间件,中间件会负责往this.files里面写东西
this.postProcessFilesCbs = []
// exit messages
this.exitLogs = []
// load all the other plugins 开发依赖加上生产依赖,过滤得到vue-cli这些插件
this.allPlugins = this.resolveAllPlugins() // @vue/cli-plugin-babel 找出这些的插件
// 默认把 @vue/cli-service 的options作为 rootOptions
const cliService = plugins.find(p => p.id === '@vue/cli-service')
const rootOptions = cliService
? cliService.options
: inferRootOptions(pkg)
this.rootOptions = rootOptions
}
id:插件的名字,如
@vue/cli-service
apply:其实就是插件的函数loadModule 其实就是为了得到插件 generator 导出的一个下面这样的函数