Vue-cli is really good?

Vue-cli is a scaffolding that integrates WebPack + VUE and makes it easy to create a VUE project, even introducing vuex and Vue-Router. Webpack configuration is transparent to users, and users do not need to pay attention to the detailed configuration of WebPack, thus improving development efficiency. So does vue-CLI really work? Let’s take a look at the Webpack configuration generated by vue-CLI. First let’s look at the import file configuration:

 entry: {
    app: './src/main.js'
 }
Copy the code

Obviously, this is a single entry file, combined with vue-Router can achieve a single page project, packaged easily, only an HTML file and the corresponding static file. This advantage is also a disadvantage: if our project is large, all the logic and business is packaged in one file. There are several disadvantages:

  1. All logic and business on one page, resulting in slow page loading
  2. Packaging and compiling time is slow, reducing development efficiency
  3. Highly coupled, when packaging, if there is a mistake in one place, packaging deployment, will result in the entire site is not accessible

These drawbacks can also be quite fatal. If you call undefined when packing, and then inadvertently publish to the Internet, your boss will have a nice chat with you next.

Based on the above, how can vue-CLI created projects be improved? The answer, of course, is to separate modules, modify the WebPack configuration, package and compile according to modules, so that you do not put all the logic into a page, compile and package according to modules, reduce the coupling degree, to facilitate the division of development (one person, one module).

transform

1. Modify the directory structure.

Original structure:

modules # All module folders└ ─ ─ ─ assetsStatic file shared by all modules│ │ CSS │ img │ js ├ ─ commonThe js code common to all modules, such as util.js└ ─ ─ ─ the componentsAll modules share a vue submodule, such as header.vue└ ─ ─ ─ the SRCThe source folder for all modules│ └ ─ ─ ─ module_name# module name│ │ └ ─ ─ ─ assets# static file specific to this module│ │ │ CSS │ │ │ img │ │ │ js │ │ └ ─ ─ ─ the componentsThis module features vUE submodule│ │ └ ─ ─ ─ the router# This module uses VUE routing Settings│ │ └ ─ ─ ─ util# This module uses the common class JS│ │ │ App. Vue# container│ │ │ index. HTMLModule template file│ │ │ main. Js# module entry file, file name do not change!!
Copy the code

The SRC folder under Modules contains all modules. Multiple modules share assets and components. Each module also has its own assets and components. By comparison, we can know that a single module under vue-CLI SRC is actually divided into multiple modules. Of course, each module if you want to follow the original VUE-CLI model for development is also possible, each module can be large or small, but it is recommended that each module is not too large, otherwise the meaning of module is not big.

2. Modify the WebPack configuration file

1, modify the webpack.base.config.js entry file:

Entry: {app: utils.getentry () // previous was./ SRC /main.js}Copy the code

Utils. GetEntry gets the entry file of the module currently under development, so we need a method to get the method of the module currently under development. My idea here is to execute a js file when we run NPM run sart/build. This js file can be prompted to get the user to input the module he wants to run, and then pass in the current module as a parameter when starting the WebPack server.

So add the start.js file to the command folder as follows:

const exec = require('child_process').exec
const { prompt } = require('inquirer')
const chalk = require('chalk'// Ask the user which module to run in the module variabletype: 'input',
    name: 'module',
    message: 'Module name:',
    validate (val) {
      if (val === ' ') {
        return 'Module name is required! '
      } 
      return true}}] module.exports = prompt(question). Then (({module}) => {// The module to run is passed as an argument to dev-server.jslet cmdStr = `node ./build/dev-server.js ${module}`
  var child = exec(cmdStr)
  child.stdout.on('data'.function(data) {
    console.log('stdout: ' + data)
  })
  child.stderr.on('data'.function(err) {
    console.log(err)
    process.exit()
  })
})
Copy the code

Build.js contains the following contents:


const { prompt } = require('inquirer')
const exec = require('child_process').exec
const chalk = require('chalk')
const ora = require('ora')

const question = [
  {
    type: 'input',
    name: 'module',
    message: 'Module name:',
    validate (val) {
      if (val === ' ') {
        return 'Module name is required! '
      } 
      return true
    }
  }
]

module.exports = prompt(question).then(({module}) => {
  const spinner = ora(`Building ${module}. ') spinn.start () // Pass the module to run as an argument to build.js var child =exec(`node ./build/build.js ${module}`)
  child.stdout.on('data', (data) => {
    console.log('stdout: ' + data)
  })

  child.stderr.on('data'.function(err) {
    console.log(chalk.red(`\n building ${module} error`))
    console.log(chalk.red(err))
    process.exit()
  })

  child.on('close'.function(code) {
    spinner.stop()
    console.log(chalk.green('Build \ n) completed! '))})})Copy the code

Argv [2] is the module name we entered because process.argv[2] is the second parameter we passed

Add the utils.js helper method

GetProjectPath = () => {console.log(fs.realpathsync (process.cwd())))returnFs.realpathsync (process.cwd())} // Get the path of the current development module, such as modules/views/test/
exports.getModulePath = () => {
  var moduleName = process.argv[2]
  return exports.getProjectPath() + '/modules/src/' + moduleName
}
Copy the code

So the entry file to get our current module looks like this:

// Get the entry file of the submodule, such as modules/views/test/main.js
exports.getEntry = () => {
  return exports.getModulePath() + '/main.js'
}
Copy the code

The file for the module that needs to be packaged looks like this:

// Get the file you want to package based on the module currently under development, exports.getouputFilename = () => {var moduleName = process.argv[2]returnexports.getProjectPath() + `/.. /${moduleName}/index.html`
}
Copy the code

4, of course, when we package, the package files need to be placed in different modules, rather than all packaged into an HTML, so modify the webpack.prod.config.js file, modify HtmlWebpackPlugin plug-in, specify the package path

new HtmlWebpackPlugin({
  filename: utils.getOuputFileName(),
  template: utils.getModuleTemplate(),
  inject: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
  }
Copy the code

5. Modify package.json file

"scripts": {
    "start": "node command/start.js cross-env NODE_ENV=develoment"."build": "node command/build.js"
  },
Copy the code

This is basically the end of the development runtime, running/packaged as modules.

Have you noticed that the directory structure of each module is almost the same? Every time we create a new module, we need to copy and paste it, which is very mechanized. So we can achieve automation.

Automatic add module

The basic idea is that we put the fixed structure of the module on Github, with my own link: github.com/VikiLee/mod… Then use the download-git-repo command to download it locally. Of course, we need to prompt the user to ask the name of the module that they want to create, and then download it from Github to the module folder. Create create.js under the command folder, and the content is as follows:

const download = require('download-git-repo')
const { prompt } = require('inquirer')
const ora = require('ora')
const chalk = require('chalk')
const fs = require('fs')

var question = [
  {
    type: 'input',
    name: 'moduleName',
    message: 'Please input module name:',
    validate(val) {
      if(val === ' ') {return 'Module name is required'
      }
      return true}}] module.exports = prompt(question). Then (({moduleName}) => {// Module existsif (fs.existsSync(`./modules/src/${moduleName}`)) {
    console.log(chalk.red(`Module '${moduleName}'exists! `)) process.exit() } const spinner = ora('Downloading template... ')
  
  spinner.start()
  download(`VikiLee/module_tempate#master`, `./modules/src/${moduleName}`, (err) => {
    if (err) {
      console.log(chalk.red(err))
      process.exit()
    }
    spinner.stop()
    console.log(chalk.green('New module has been created successfully! '))})})Copy the code

Also modify the package.json file and add the create command

"scripts": {
    "create": "node command/create.js"."start": "node command/start.js cross-env NODE_ENV=develoment"."build": "node command/build.js"
  },
Copy the code

This creates new modules in an automated manner.

Git address: github.com/VikiLee/web…