Interpretation of vue-cli scaffolding (2): Behind the npm run build

If you haven't read my last article, please take a look at it first!

After more than a year, the article I wrote before felt that everyone liked it, and I kept saying that I would update the next one. But there has been no chance, no time, and that is, I feel that my skills may not be enough to support me to continue going down. But after more than a year of experience, I feel that a lot of things will be considered more comprehensively and live up to expectations!

Talk about a bunch of nonsense and get to the point.

I. Introduction

It is necessary to state here that I 2018-09-19 published the last article  , that is to say, at least one and a half years have passed since now (2020-02-03), the original has  vue-cli become  vue@cli scaffolding and project engineering has become It's totally unrecognizable and very different from the original. Is the current article still worth reading?

My point is : It mainly depends on what position you hold to read this article, if you want to rush to solve some problems encountered in the project. Maybe this article is not very suitable for you, because you will not have an immediate effect after reading it, and it will not help you solve your problem immediately.
But if you want to go to a higher stage, or satisfy your previous curiosity, why this scaffold can pack the things needed for the project, and how does this work? Then this article is worth reading for you.
Because, despite the vue@cli upgrade, the method of application is different, and the project structure has changed. But what I want to say is that if you are familiar with the bottom layer, project structure, scaffolding, these things feel like just changing the soup, not the medicine. In the end webpack , the project is organized around  , and then a variety of powerful plug-ins are used in the middle!

2. /config /build The mystery of documents

After the last article is finished  npm ru dev , the command line parsing and the file to be executed are stopped, so here we start from the final parsing of the executed  /config /build file.

(1)  The project we created using the 2.X version of the scaffold is probably like this, and then we focus on the files below the two files generated by the scaffold by default. Here is the script for running and building the project.
Insert picture description here
(2)  Here we only need to pay attention  /build to the file configuration under the directory, this is the file configuration of the scaffolding.
According  npm run dev After command execution, execution is final:
webpack-dev-server --inline --progress --config build/webpack.dev.conf.js

Then finally find: build/webpack.dev.conf.js the contents of the file.

(3)webpack.dev.conf.js  The content of the file  we are looking at  :

'use strict'
const utils = require('./utils') // 就是一些工具函数,用到具体去看就好了
const webpack = require('webpack') // 这个是 webpack 插件
const config = require('../config') // 项目里面的配置
const merge = require('webpack-merge') // 合同配置的函数是,感觉很有意思,可以去了解一下
const path = require('path') // 解析路径的函数,返回一个绝对路径,也很有意思,建议去看看具体 Api
const baseWebpackConfig = require('./webpack.base.conf') // 构建的一些通用的配置项
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder') // 确定可用端口的插件

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },
  // cheap-module-eval-source-map is faster for development
  devtool: config.dev.devtool,

  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // copy custom static assets
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

const print = (options, reject) => {
  let res = '{'
  Object.keys(options).forEach(o => {
    res = res + `"${o}":` + JSON.stringify(options[o]) + ','
  })
  console.log(`==res================`)
  console.log(res + '}')
  console.log('==================')
  reject()
}

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port // 设置需要确定或是可用的端口
  portfinder.getPort((err, port) => {
    if (err) {
      reject(err)
    } else {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
        },
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))

      print(devWebpackConfig, reject)
      resolve(devWebpackConfig)
    }
  })
})

 

There is not much code, just a hundred lines of code. The core idea is: return a webpack configuration.
This is why webpack is so important that we have previously had hot development updates, packaging, and automatic style prefixes...
all of these capabilities are Completed on the basis of webpack.

(4)  Let's look at the specific content.
The first is to introduce various plug-ins first, and their functions in the code are given their meanings through comments.
There is also the introduction of a common configuration: const baseWebpackConfig = require('./webpack.base.conf')
here to talk about why a separate common configuration is separated: mainly because some of the same configuration that is debugged during production package can be used together, and then there are differences through the object The way of merging, the latter covers the former, and then achieves the purpose of privatization configuration of each environment.

Next, let's take a look at the specific code. (See the steps marked in the picture)
Insert picture description here

Finally, I wrote a print() function to print the final configuration. If you are interested, you can check it out, hahaha.

Third, the second step: npm run build

We have read the  run dev startup items, and then look at the packaging project, this is very simple. Because the general process is the same: it is all about generating a configuration item, passing it to webpack, and then packaging and building the final product.
Let's take a look at it roughly:
Insert picture description here
During execution  npm run build , the final code to be executed is the /build.js file. This is the same as before, all by introducing public configuration items, then merging private configurations, and finally generating configurations, and then packaging. It's also relatively simple, so I will leave it to everyone to take a look.

Four, summary

Here I feel that even if the article on analyzing scaffolding is finished, there is only one general idea: generate the configuration items required by webpack.
No matter how fancy the project's scaffolding and configuration are, a configuration item will eventually be exported.
So here are some small ideas for you to configure your own things in the future, I hope these two articles can give you a little bit of inspiration!

PS: If there is something wrong in the article, please correct me!

Guess you like

Origin blog.csdn.net/weixin_43452467/article/details/110221381