This is the 7th day of my participation in Gwen Challenge

In the implementationnpm run buildThen the construction process of the project

All of the code

const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const rollup = require('rollup')
const terser = require('terser')

if(! fs.existsSync('dist')) {
  fs.mkdirSync('dist')}let builds = require('./config').getAllBuilds()

if (process.argv[2]) {
  const filters = process.argv[2].split(', ')
  builds = builds.filter(b= > {
    return filters.some(f= > b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)})}else {
  // filter out weex builds by default
  builds = builds.filter(b= > {
    return b.output.file.indexOf('weex') = = = -1
  })
}

build(builds)

function build (builds) {
  let built = 0
  const total = builds.length
  const next = () = > {
    buildEntry(builds[built]).then(() = > {
      built++
      if (built < total) {
        next()
      }
    }).catch(logError)
  }

  next()
}

function buildEntry (config) {
  const output = config.output
  const { file, banner } = output
  const isProd = /(min|prod)\.js$/.test(file)
  return rollup.rollup(config)
    .then(bundle= > bundle.generate(output))
    .then(({ output: [{ code }] }) = > {
      if (isProd) {
        const minified = (banner ? banner + '\n' : ' ') + terser.minify(code, {
          toplevel: true.output: {
            ascii_only: true
          },
          compress: {
            pure_funcs: ['makeMap']
          }
        }).code
        return write(file, minified, true)}else {
        return write(file, code)
      }
    })
}

function write (dest, code, zip) {
  return new Promise((resolve, reject) = > {
    function report (extra) {
      console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ' '))
      resolve()
    }
    fs.writeFile(dest, code, err= > {
      if (err) return reject(err)
      if (zip) {
        zlib.gzip(code, (err, zipped) = > {
          if (err) return reject(err)
          report(' (gzipped: ' + getSize(zipped) + ') ')})}else {
        report()
      }
    })
  })
}

function getSize (code) {
  return (code.length / 1024).toFixed(2) + 'kb'
}

function logError (e) {
  console.log(e)
}

function blue (str) {
  return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}

Copy the code

The code analysis

  • if(! fs.existsSync('dist')) {
      fs.mkdirSync('dist')}Copy the code
    • Determine if it already existsdistDirectory, create a directory if it does not exist
  • let builds = require('./config').getAllBuilds()
    Copy the code
    • Get all the configuration data in the./config file and convert it to a format suitable for rollup

    • The configuration fileconfig.js

      • exports.getAllBuilds = () = > Object.keys(builds).map(genConfig)
        
        function genConfig (name) {
            const opts = builds[name]
            const config = {
                input: opts.entry,
                external: opts.external,
                plugins: [
                    flow(),
                    alias(Object.assign({}, aliases, opts.alias))
                ].concat(opts.plugins || []),
                output: {
                    file: opts.dest,
                    format: opts.format,
                    banner: opts.banner,
                    name: opts.moduleName || 'Vue'
                },
                onwarn: (msg, warn) = > {
                    if (!/Circular/.test(msg)) {
                        warn(msg)
                    }
                }
            }
            
        const builds = {
          'web-runtime-cjs-dev': {
            entry: resolve('web/entry-runtime.js'), // Import file
            dest: resolve('dist/vue.runtime.common.dev.js'),// Export file
            format: 'cjs'.// is in common. Js or es6 format
            env: 'development',
            banner // Comments above the file},... Other Configuration data}}Copy the code
        • genConfigIs mainly tobuildsConfigure the data in therollupThe required format
  • if (process.argv[2]) {
      const filters = process.argv[2].split(', ')
      builds = builds.filter(b= > {
        return filters.some(f= > b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)})}else {
      builds = builds.filter(b= > {
        return b.output.file.indexOf('weex') = = = -1})}Copy the code
    • processisnodeOf a process-related global variable, whereprocess.argv[0]Represents the path to the executable that started the process,process.argv[1]Represents the path of the js file currently executed,process.argv[2]Represents additional command line arguments
    • node scripts/build.js "web-runtime-cjs,web-server-renderer"Among themprocess.argv[2]isweb-runtime-cjs,web-server-renderer
    • In the implementationnpm run buildIs actually executingnode node scripts/build.js; So what we’re currently gettingprocess.argv[2]If it is empty, execute itelseThe contents of thebuildData is filtered, filtered outbuildIs contained in the output fileweexThe object of
  • build(builds)
    
    function build (builds) {
      let built = 0
      const total = builds.length
      const next = () = > {
        buildEntry(builds[built]).then(() = > {
          built++
          if (built < total) {
            next()
          }
        }).catch(logError)
      }
    
      next()
    }
    
    Copy the code
    • In order tobuildsConfiguration execution inbuildEntrythenextMethod implementations are executed in sequence.
  • function buildEntry (config) {
      const output = config.output
      const { file, banner } = output
      const isProd = /(min|prod)\.js$/.test(file)
      return rollup.rollup(config)
        .then(bundle= > bundle.generate(output))
        .then(({ output: [{ code }] }) = > {
          if (isProd) {
            const minified = (banner ? banner + '\n' : ' ') + terser.minify(code, {
              toplevel: true.output: {
                ascii_only: true
              },
              compress: {
                pure_funcs: ['makeMap']
              }
            }).code
            return write(file, minified, true)}else {
            return write(file, code)
          }
        })
    }
    Copy the code
    • Gets the name of the file output from the configuration objectfileandbannerFile warning
    • Determine whether the file name needs to be compressed and then write the file
    • Otherwise just write the code directly, where the compressed code is mostly usedzlib.gzipfor