vueソース解析のnpm run buildで何が起こったの?

26563 ワード

npm run buildで何があったの?
最近いつもvueのいくつかの用法と文に対してまだ理解していないと感じて、そこでソースコードを引っ張って、自分のvueに対する理解を深めるために使うことを决めて、同时にvueは主にrollupを通じてパッケージのコンパイルを行って、それはwebpackに比べて更に軽くて、いいです、くだらないことは多く言わないで、始まりました!
上図に示すように、npm runbuildコマンドを実行するときは、まずpackage.jsonはそれをnode build/buildと解析する.js、このディレクトリを実行して、このディレクトリが何なのか見てみましょう.
コードを理解するのが難しい場合は、ファイルコードの下に整理されます!
直接build/buildに入ります.jsシールコード!
const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const rollup = require('rollup')
const uglify = require('uglify-js')

if (!fs.existsSync('dist')) {  //       dist   ,         
  fs.mkdirSync('dist')  //       ,      build   ,     dist   
}

let builds = require('./config').getAllBuilds()  //   ./config    ,          getAllBuilds()  
//process.argv            : node app 127.0.0.1 7001       127.0.0.1
if (process.argv[2]) {  //      build:ssr week   
  const filters = process.argv[2].split(',')  //           
  builds = builds.filter(b => {                                                         //      .output.file ._name  filters   
    return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1) //           ,    true    false
  })
} else {  //              npm run build
  // filter out weex builds by default  //   weex     
  builds = builds.filter(b => {    //           weex 
    return b.output.file.indexOf('weex') === -1
  })
}   //      ,    builds         


build(builds)

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

  next()
}

function buildEntry (config) {  //       rollup      
  const output = config.output
  const { file, banner } = output
  const isProd = /min\.js$/.test(file)  //   min.js     
  return rollup.rollup(config)
    .then(bundle => bundle.generate(output))
    .then(({ code }) => {
      if (isProd) {
        var minified = (banner ? banner + '
'
: '') + uglify.minify(code, { // js 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 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' }

コードの解析を開始します
最初の2行は主にいくつかのモジュールを導入し、distファイルの判断は、注釈を通じて、きっと理解できると信じています.
let builds = require('./config').getAllBuilds()
次にこのbuildsが何なのか見てみましょう.まずconfigフォルダの下のコードを見てみましょう.
JavaScriptの例:
const path = require('path')
const buble = require('rollup-plugin-buble')
const alias = require('rollup-plugin-alias')
const cjs = require('rollup-plugin-commonjs')
const replace = require('rollup-plugin-replace')
const node = require('rollup-plugin-node-resolve')
const flow = require('rollup-plugin-flow-no-whitespace')
const version = process.env.VERSION || require('../package.json').version
const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version
 //           
const banner =
  '/*!
'
+ ' * Vue.js v' + version + '
'
+ ' * (c) 2014-' + new Date().getFullYear() + ' Evan You
'
+ ' * Released under the MIT License.
'
+ ' */' const weexFactoryPlugin = { intro () { return 'module.exports = function weexFactory (exports, document) {' }, outro () { return '}' } } const aliases = require('./alias') // alias const resolve = p => { const base = p.split('/')[0] // / if (aliases[base]) { // aliases , return path.resolve(aliases[base], p.slice(base.length + 1)) // p.slice(base.length + 1) ‘/’ } else { return path.resolve(__dirname, '../', p) // dist } } // entry , rollup input dest , rollup output format banner , const builds = { // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify 'web-runtime-cjs': { entry: resolve('web/entry-runtime.js'), dest: resolve('dist/vue.runtime.common.js'), format: 'cjs', banner }, // Runtime+compiler CommonJS build (CommonJS) 'web-full-cjs': { entry: resolve('web/entry-runtime-with-compiler.js'), dest: resolve('dist/vue.common.js'), format: 'cjs', alias: { he: './entity-decoder' }, banner }, // Runtime only (ES Modules). Used by bundlers that support ES Modules, // e.g. Rollup & Webpack 2 'web-runtime-esm': { entry: resolve('web/entry-runtime.js'), dest: resolve('dist/vue.runtime.esm.js'), format: 'es', banner }, // Runtime+compiler CommonJS build (ES Modules) 'web-full-esm': { entry: resolve('web/entry-runtime-with-compiler.js'), dest: resolve('dist/vue.esm.js'), format: 'es', alias: { he: './entity-decoder' }, banner }, // runtime-only build (Browser) 'web-runtime-dev': { entry: resolve('web/entry-runtime.js'), dest: resolve('dist/vue.runtime.js'), format: 'umd', env: 'development', banner }, // runtime-only production build (Browser) 'web-runtime-prod': { entry: resolve('web/entry-runtime.js'), dest: resolve('dist/vue.runtime.min.js'), format: 'umd', env: 'production', banner }, // Runtime+compiler development build (Browser) 'web-full-dev': { entry: resolve('web/entry-runtime-with-compiler.js'), dest: resolve('dist/vue.js'), format: 'umd', env: 'development', alias: { he: './entity-decoder' }, banner }, // Runtime+compiler production build (Browser) 'web-full-prod': { entry: resolve('web/entry-runtime-with-compiler.js'), dest: resolve('dist/vue.min.js'), format: 'umd', env: 'production', alias: { he: './entity-decoder' }, banner }, // Web compiler (CommonJS). 'web-compiler': { entry: resolve('web/entry-compiler.js'), dest: resolve('packages/vue-template-compiler/build.js'), format: 'cjs', external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies) }, // Web compiler (UMD for in-browser use). 'web-compiler-browser': { entry: resolve('web/entry-compiler.js'), dest: resolve('packages/vue-template-compiler/browser.js'), format: 'umd', env: 'development', moduleName: 'VueTemplateCompiler', plugins: [node(), cjs()] }, // Web server renderer (CommonJS). 'web-server-renderer': { entry: resolve('web/entry-server-renderer.js'), dest: resolve('packages/vue-server-renderer/build.js'), format: 'cjs', external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies) }, 'web-server-basic-renderer': { entry: resolve('web/entry-server-basic-renderer.js'), dest: resolve('packages/vue-server-renderer/basic.js'), format: 'umd', env: 'development', moduleName: 'renderVueComponentToString', plugins: [node(), cjs()] }, 'web-server-renderer-webpack-server-plugin': { entry: resolve('server/webpack-plugin/server.js'), dest: resolve('packages/vue-server-renderer/server-plugin.js'), format: 'cjs', external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies) }, 'web-server-renderer-webpack-client-plugin': { entry: resolve('server/webpack-plugin/client.js'), dest: resolve('packages/vue-server-renderer/client-plugin.js'), format: 'cjs', external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies) }, // Weex runtime factory 'weex-factory': { weex: true, entry: resolve('weex/entry-runtime-factory.js'), dest: resolve('packages/weex-vue-framework/factory.js'), format: 'cjs', plugins: [weexFactoryPlugin] }, // Weex runtime framework (CommonJS). 'weex-framework': { weex: true, entry: resolve('weex/entry-framework.js'), dest: resolve('packages/weex-vue-framework/index.js'), format: 'cjs' }, // Weex compiler (CommonJS). Used by Weex's Webpack loader. 'weex-compiler': { weex: true, entry: resolve('weex/entry-compiler.js'), dest: resolve('packages/weex-template-compiler/build.js'), format: 'cjs', external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies) } } function genConfig (name) { /// builds rollup , entry input const opts = builds[name] const config = { input: opts.entry, external: opts.external, plugins: [ replace({ __WEEX__: !!opts.weex, __WEEX_VERSION__: weexVersion, __VERSION__: version }), flow(), buble(), alias(Object.assign({}, aliases, opts.alias)) ].concat(opts.plugins || []), output: { file: opts.dest, format: opts.format, banner: opts.banner, name: opts.moduleName || 'Vue' } } if (opts.env) { config.plugins.push(replace({ 'process.env.NODE_ENV': JSON.stringify(opts.env) })) } Object.defineProperty(config, '_name', { enumerable: false, value: name }) return config } if (process.env.TARGET) { // TARGET module.exports = genConfig(process.env.TARGET) } else { exports.getBuild = genConfig exports.getAllBuilds = () => Object.keys(builds).map(genConfig) // builds , genConfig }

次に、最もパッケージ化されたコンパイル全体を整理します.
ビルドファイルを実行すると、モジュールを導入すると、./configでbuildsを手に入れましたが、buildsは何ですか?
configファイルの末尾にこのようなコードがあります.
最後の行でbuildsを手に入れたのでkeysが遍歴しgenConfigメソッドを実行していることが明らかになった.
上図から分かるようにbuildsはファイル情報を含むオブジェクトであり、rollupパラメータのマッピングに相当し、entryはエントリであり、rollupに対応するinput、destはエクスポートであり、rollupに対応するoutput、formatはフォーマットであり、bannerはバージョン注釈である.
このオブジェクトはキーを介してgenConfigメソッドに渡されますが、genConfigとは何ですか?見てみましょう
genConfigメソッドは、buildsオブジェクトをrollupで使用されるフォーマットに変換する方法であり、rollup情報を含むフォーマットがbuildsファイルの変数builds、すなわち最初に述べたものであることがわかります.
次にbuildファイルのコードを見てみましょう
次はプロセスを取得します.argv[2]は、コンパイルする必要のないファイルをフィルタリングし、注釈は十分詳細で、あまり説明したくない.
次にbuild()メソッドを実行します.buildメソッドはループであり、buildEntry()メソッドをループで実行していることがわかります.
buildEntryは、rollupの実行を本格的に開始し、返されたbuildsをコンパイルし、対応するファイルを生成します.
このように全体のコンパイルの過程は実行し終わって、役に立つと思って、気をつけましょう!