This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

In the previous note: Vuex 4 source Code Study Notes – Unit Testing tool functions (vii)

We learned the tool functions used by Vuex through unit tests.

Let’s see what we can learn from Vuex’s NPM Run build today

First we can see from scripts in package.json that we are actually using Node to run scripts/build.js

"scripts": {
  / /...
  "build": "node scripts/build.js"./ /...
}
Copy the code

Open the scripts/build.js file

// fs-extra is an alternative to native FS. All methods in FS are attached to FS-extra. If the callback fails, all fs methods return a Promise.
const fs = require('fs-extra')
// Chalk is used to output strings with styles in the terminal
const chalk = require('chalk')
// execa is used to run various commands in Node.js
const execa = require('execa')
// Gzip compressed file
const { gzipSync } = require('zlib')
// Brotli compressed file algorithm
const { compress } = require('brotli')

const files = [
  'dist/vuex.esm-browser.js'.'dist/vuex.esm-browser.prod.js'.'dist/vuex.esm-bundler.js'.'dist/vuex.global.js'.'dist/vuex.global.prod.js'.'dist/vuex.cjs.js'
]

async function run() {
  await Promise.all([build(), copy()])
  checkAllSizes()
}

async function build() {
  await execa('rollup'['-c'.'rollup.config.js'] and {stdio: 'inherit'})}async function copy() {
   await fs.copy('src/index.mjs'.'dist/vuex.mjs')}function checkAllSizes() {
  console.log()
  files.map((f) = > checkSize(f))
  console.log()
}

function checkSize(file) {
  const f = fs.readFileSync(file)
  const minSize = (f.length / 1024).toFixed(2) + 'kb'
  const gzipped = gzipSync(f)
  const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb'
  const compressed = compress(f)
  const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'
  console.log(
    `${chalk.gray( chalk.bold(file) )} size:${minSize} / gzip:${gzippedSize} / brotli:${compressedSize}`
  )
}

run()
Copy the code

The main NPM packages this file relies on are:

  • fs-extra: FS-Extra is an alternative to native FS. All methods in FS are attached to FS-extra. If the callback fails, all fs methods return a Promise.
  • chalk: Used to print a styled string in a terminal
  • execa: is used to run various commands in Node.js
  • zlib: Gzip compressed file
  • brotli: Brotli compression file algorithm

This file does three main things:

  • build()Function is used to userollupTo pack
  • copy()Function is used to bringsrc/index.mjsCopy files todist/vuex.mjs
  • checkAllSizes()The function checks the size of each packaged file

Next up is the rollup configuration file rollup.config.js that is important to package the source code using rollup

import buble from '@rollup/plugin-buble'
import replace from '@rollup/plugin-replace'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import { terser } from 'rollup-plugin-terser'
import pkg from './package.json'

const banner = ` / *! * vuex v${pkg.version}
 * (c) The ${new Date().getFullYear()} Evan You
 * @license MIT
 */`

const configs = [
  // The browser introduces the development version of ES Module
  { input: 'src/index.js'.file: 'dist/vuex.esm-browser.js'.format: 'es'.browser: true.env: 'development' },
  // The browser introduces the production version of ES Module
  { input: 'src/index.js'.file: 'dist/vuex.esm-browser.prod.js'.format: 'es'.browser: true.env: 'production' },
  // import Vuex from 'Vuex'
  { input: 'src/index.js'.file: 'dist/vuex.esm-bundler.js'.format: 'es'.env: 'development' },
  // Browser CDN introduction of the development version
  { input: 'src/index.cjs.js'.file: 'dist/vuex.global.js'.format: 'iife'.env: 'development' },
  // The production version introduced in browser CDN mode
  { input: 'src/index.cjs.js'.file: 'dist/vuex.global.prod.js'.format: 'iife'.minify: true.env: 'production' },
  // Require ('vuex')
  { input: 'src/index.cjs.js'.file: 'dist/vuex.cjs.js'.format: 'cjs'.env: 'development'}]function createEntries () {
  return configs.map((c) = > createEntry(c))
}

function createEntry (config) {
  const isGlobalBuild = config.format === 'iife'
  constisBundlerBuild = config.format ! = ='iife' && !config.browser
  const isBundlerESMBuild = config.format === 'es' && !config.browser

  const c = {
    external: ['vue'].// The ID of the module to exclude, excluding vUE dependencies
    input: config.input, // Import file address
    plugins: [].// All plug-ins
    output: {
      banner, // The code inserted at the top of the packaged file
      file: config.file, // Output file address
      format: config.format, // Output type (AMD, CJS, ES, IIFE, UMD, SYSTEM)
      globals: { // Tell Rollup that Vue is an external dependency
        vue: 'Vue'
      }
      /* var MyBundle = (function (Vue) { // code goes here }(Vue)); * /
    },
    // A function that intercepts warning messages
    onwarn: (msg, warn) = > {
      if (!/Circular/.test(msg)) {
        warn(msg)
      }
    }
  }

  if (isGlobalBuild) {
    // Is required for exported Iife/UMD packages and represents the global variable name of the package.
    c.output.name = c.output.name || 'Vuex'
  }

  if(! isGlobalBuild) {// Exclude @vue/devtools-api dependencies
    c.external.push('@vue/devtools-api')}// the Rollup plugin replaces the target string in the file when packaging.
  c.plugins.push(replace({
    preventAssignment: true.__VERSION__: pkg.version,
    __DEV__: isBundlerBuild
      ? `(process.env.NODE_ENV ! == 'production')`: config.env ! = ='production'.__VUE_PROD_DEVTOOLS__: isBundlerESMBuild
      ? '__VUE_PROD_DEVTOOLS__'
      : 'false'
  }))

  // A Rollup plug-in that converts ES2015+ code using the Buble compiler.
  if(config.transpile ! = =false) {
    c.plugins.push(buble())
  }

  // a Rollup plugin that uses Node parsing algorithms to locate modules for use with third-party modules in node_modules
  c.plugins.push(resolve())
  // A Rollup plugin for converting CommonJS modules to ES6
  c.plugins.push(commonjs())

  // Rollup plugin to shrink the generated ES package.
  if (config.minify) {
    c.plugins.push(terser({ module: config.format === 'es'}}))return c
}

export default createEntries()
Copy the code

Rollup packaging uses the following plug-in features:

  • @rollup/plugin-buble: Rollup plug-in to convert ES2015+ code using the Buble compiler.
  • @rollup/plugin-replace: Replaces the target string in the file when packaging.
  • @rollup/plugin-node-resolve: Rollup plug-in that uses Node parsing algorithms to locate modules for use with third-party modules in node_modules
  • @rollup/plugin-commonjs: Used to convert CommonJS modules to ES6
  • rollup-plugin-terser: Used to shrink the generated ES package.

The target products of packaging are as follows:

  • Dist /vuex.esm-browser.js: For import use via native ES modules (use in browsers via

  • Dist/vuex.esM-browser.prod. js: Same as above, as the production version.

  • Dist/vuex.esM-Bundler.js: ES modular approach introduces import vuex from ‘vuex’ for webpack, rollup and Parcel build tools, no compressed version is available (packaged and compressed with the rest of the code).

  • Dist /vuex.global.js: Development version introduced in browser CDN mode

  • Dist /vuex.global.prod.js: production version introduced by browser CDN

  • Dist /vuex.cjs.js: CommonJS module approach introduces const vuex = require(‘vuex’), which is rendered on the Node.js server side by require().

Each product corresponds to a different use platform.

Learn more front-end knowledge together, wechat search [Xiaoshuai’s programming notes], updated every day