vue create preliminary analysis and customized modification

Version Description

$ vue --version
@vue/cli 4.5.9
$ node --version
v14.0.0
$ npm --version
7.6.1

Source location - mac

/usr/local/lib/node_modules/@vue/cli

Process description

  1. According to package Bin in JSON can know that the entry file is in bin / Vue js
  2. vue. The command setting of create <app-name> is found in JS, and lib/create is invoked in the action hook.

create.js

  1. Get project absolute path
  2. Determine whether the project folder exists
  3. create folder
  4. Call lib / creator js

Creator.js

Creator.create()

  1. Configure the preset plug-in group according to the selection when creating the project

  2. Deep copy preset

  3. Configure the configuration items of the default plug-in in preset: @ Vue / cli service, @ Vue / cli plugin router, @ Vue / cli plugin typescript, @ Vue / cli plugin vuex

  4. Get package manager: yarn/npm/pnpm

  5. Start creating the project and get the Vue cli version

  6. Generate package according to the plug-in configuration in preset JSON file

  7. Generate for pnpm npmrc file, generated for yarn yarnrc

  8. Add git configuration for the project: git init

  9. Installing the CLI plug-in: generates a file directory in the specified format

    await generator.generate({
      extractConfigFiles: preset.useConfigFiles,
    });
    
  10. Wake up plug-in

  11. Install and configure additional dependencies

  12. running completion hooks

  13. Generate readme md

  14. Configure the state of GIT and configure git for the test

  15. complete

Custom modify scaffold program

The plug-ins and other configurations used in the company's projects are basically similar, and there are many ways to improve development efficiency in the project development process, which can be customized in the scaffold program flow

  1. Get rid of the duplicate work of copy and paste, and avoid the bug that can not be debug ged caused by the loss of copy and paste
  2. Improve project development efficiency and unify project development style

Generate Vue config. JS - generate readme md

  1. generateVueConfig.js
// Generate readme md: lib/util/generateReademe.js
// Generate Vue config. js: lib/util/generateVueConfig.js, I have other configuration items, which need to generate Vue according to the configuration config. js
module.exports = function generateVueConfig(plugins) {
  const iconSvg = plugins['svg-sprite-loader'] ? `chainWebpack: config => {
    // svg rule loader
    const svgRule = config.module.rule('svg') // Find SVG loader
    svgRule.uses.clear() // Clear the existing loader. If not, it will be added after this loader
    svgRule.exclude.add(/node_modules/) // Regular match exclusion node_modules directory
    svgRule // Add svg new loader handling
      .test(/\.svg$/)
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]',
      })

    // Modify images loader and add svg processing
    const imagesRule = config.module.rule('images')
    imagesRule.exclude.add(resolve('src/icon/svg'))
    config.module
      .rule('images')
      .test(/\.(png|jpe?g|gif|svg)(\?.*)?$/)
  }` : ''

  return `const path = require('path')

function resolve(dir) {
  return path.join(__dirname, './', dir)
}
module.exports = {
  publicPath: './',
  devServer: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true
      }
    }
  },
  productionSourceMap: false,
  ${iconSvg}
}`
}
  1. Modify the create process - creator js

    // Custom build Vue config. js, write the configuration used many times, such as cross domain configuration. You can write it directly or write the content in another js file and import it
    if (!generator.files['vue.config.js']) {
      log()
      log('⚙\u{fe0f}  Generating vue.config.js...')
      await writeFileTree(context, {
        'vue.config.js': generateVueConfig(preset.otherPlugins),
      })
    }
    

Configure and import custom npm package - imitation configuration @ Vue / cli XXX package

During development, some packages will always be introduced, such as axios, encrypted packages, UI framework packages, etc. they can be added during the early selection of vue create to generate code.

Process of importing @ Vue / cli XXX package:

  1. create.js, enter the overall process according to the new Creator. When initializing the Creator, the initial package list is passed in. Only the important codes are summarized below
// create.js
const { getPromptModules } = require('./util/createTools')
const creator = new Creator(name, targetDir, getPromptModules())
// getPromptModules()
exports.getPromptModules = () => {
  return [
    'vueVersion',
    'babel',
    'typescript',
    'pwa',
    'router',
    'vuex',
    'cssPreprocessors',
    'linter',
    'unit',
    'e2e'
  ].map(file => require(`../promptModules/${file}`))
}

  1. When initializing Creator, the promptmodule API is called, the related package is introduced, and the configuration command lib/promptModules/xxx of the related package is called
// Creator.js
constructor(name, context, promptModules) {
  const promptAPI = new PromptModuleAPI(this);
  promptModules.forEach((m) => m(promptAPI));
  // After the above commands are executed, the configuration commands of each related package will be displayed in the shell interface. At this time, the user can select or enter
}
  1. In creator In the create () method, configuration items are configured for each package according to preset and stored in preset In plugins
// Creator. JS create () method, the following is only an example 
preset.plugins["@vue/cli-service"] = Object.assign(
  {
    projectName: name,
  },
  preset
);

if (cliOptions.bare) {
  preset.plugins["@vue/cli-service"].bare = true;
}

// legacy support for router
if (preset.router) {
  preset.plugins["@vue/cli-plugin-router"] = {};

  if (preset.routerHistoryMode) {
    preset.plugins["@vue/cli-plugin-router"].historyMode = true;
  }
}

Copy the above process to import the packages you want to import during initialization, such as axios. In order to avoid conflicts, all the codes are developed separately. The following examples are axios and optional UI framework

  1. createOtherTools.js - copy the getPromptModules function, configure the custom package list, and add it to the initialization Creator
// lib/util/createOtherTools. The JS othermodules folder stores the command line associated with the custom package
exports.getOtherPromptModules = () => {
  return [
    'axios',
    'uiStruct'
  ].map(file => require(`../otherModules/${file}`))
}
// create.js
const { getPromptModules } = require('./util/createTools')
const { getOtherPromptModules } = require('./util/createOtherTools')
const creator = new Creator(name, targetDir, getPromptModules(), getOtherPromptModules())
  1. Import the command line configuration of related packages and store the configuration of custom packages in options In otherplugins
// Creator.js
constructor(name, context, promptModules, otherPromptModules) {
  const promptAPI = new PromptModuleAPI(this);
  promptModules.forEach((m) => m(promptAPI));
  otherPromptModules.forEach((m) => m(promptAPI));
  // After the above commands are executed, the configuration commands of each related package will be displayed in the shell interface. At this time, the user can select or enter
}
// New otherModules folder
// otherModules/axios.js
module.exports = cli => {
  cli.injectFeature({
    name: 'Axios',  // The name displayed in the selection after the vue create command
    value: 'axios',  // Corresponding value
    description: 'Promise based HTTP client for the browser and node.js',  // introduce
    link: 'https://github.com/mzabriskie/axios', / / related links
    checked: true  // It is displayed in the options after vue create command. Is it selected by default
  })

  cli.onPromptComplete((answers, options) => {
    if (answers.features.includes('axios')) {  // Whether the includes(value) contains the value defined above
      options.otherPlugins['axios'] = {}  // Specify the corresponding enrollment here
    }
  })
}
// otherModules/uiStruct.js
module.exports = cli => {
  cli.injectFeature({
    name: 'Choose UI Struct',  // The name displayed in the selection after the vue create command
    value: 'ui-struct',  // Corresponding value
    description: 'Choose a struct of UI that you want to use with the project'  // introduce
  })

  cli.injectPrompt({
    name: 'uiStruct',
    when: answers => answers.features.includes('ui-struct'),  // Judge whether to select
    message: 'Choose a struct of UI that you want to use with the project',  // describe
    type: 'list',  // Select a shell like command
    choices: [
      {
        name: 'ant-design-vue',  // Option name
        value: 'ant-design-vue'  // Package name corresponding to option
      },
      {
        name: 'element-ui',
        value: 'element-ui'
      }
    ],
    default: 'element-ui'  // Default options
  })

  cli.onPromptComplete((answers, options) => {
    if (answers.uiStruct) {
      options.otherPlugins[answers.uiStruct] = {}  // answers.uiStruct stores the package name
    }
  })
}

  1. Add the introduction of customized package into the process and generate package Introduced before JSON
// Creator.js - create() function
if (preset.otherPlugins) {
  Object.keys(preset.otherPlugins).forEach((dep) => {
    let { version } = preset.otherPlugins[dep];
    pkg.dependencies[dep] = version ? version : "latest";
  });
}

Keywords: Vue

Added by duk on Sun, 02 Jan 2022 11:39:46 +0200