VueCli番外-写入主文件

通过 generator 方法你能够修改项目中的文件。最有用的场景是针对 main.js 或 main.ts 文件的一些修改:新的导入,新的 Vue.use() 调用等。

传送门

背景

当你使用vue-cli创建项目时,如果你选择插件,它会询问你是否需要集成vuex,router等插件,如果选择需要,那么vue-cli就会将其注入到package.json中,并修改main.js如下:

VueCli番外-写入主文件

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

main.js此时会变成以上内容,那这个“变”是如何实现的呢?

VueCli番外-写入主文件

先大致瞄一眼示意图,可以看到设计到两个文件:

  • packages/@vue/cli/lib/Create.js
  • packages/@vue/cli/lib/Generator.js

我们假设你有一个自定义插件 vue-cli-plugin-my ,并且该插件存在generator.js文件,该文件内容如下:

// generator.js

module.exports.hooks = (api) => {
  api.afterInvoke(() => {
    const { EOL } = require('os')
    const fs = require('fs')
    const contentMain = fs.readFileSync(api.resolve(api.entryFile), { encoding: 'utf-8' })
    const lines = contentMain.split(/\r?\n/g)

    const renderIndex = lines.findIndex(line => line.match(/render/))
    lines[renderIndex] += `${EOL}  my,`

    fs.writeFileSync(api.entryFile, lines.join(EOL), { encoding: 'utf-8' })
  })
}

该文件作用就是将你的自定义插件注入到new Vue() 依赖中。

afterInvoke 存在于Generator.js initPlugins 方法中,而 initPlugins方法则是由 Create.js 调用

Create.js    

   const plugins = await this.resolvePlugins(preset.plugins, pkg)
    const generator = new Generator(context, {
      pkg,
      plugins,
      afterInvokeCbs,
      afterAnyInvokeCbs
    })
    await generator.generate({
      extractConfigFiles: preset.useConfigFiles
    })
Generator.js    

// apply generators from plugins
    for (const plugin of this.plugins) {
      const { id, apply, options } = plugin
      const api = new GeneratorAPI(id, this, options, rootOptions)
      // QIU:const apply = loadModule(`${id}/generator`, this.context) || (() => {})
      await apply(api, options, rootOptions, invoking)
      // QIU: 设置插件的生命钩子函数
      if (apply.hooks) {
        // while we execute the entire `hooks` function,
        // only the `afterInvoke` hook is respected
        // because `afterAnyHooks` is already determined by the `allPluginIds` loop above
        await apply.hooks(api, options, rootOptions, pluginIds)
      }
    }

钩子的收集和调用挂载在GeneratorAPI上。

结合源码阅读,再认真理解下面这个图:

VueCli番外-写入主文件

当然,一定要结合完整的源码阅读才能掌握其中精髓

 

上一篇:selenium、验证码、cookies(python爬虫进阶


下一篇:Web测试