vueソース解析のnpm run buildで何が起こったの?
26563 ワード
npm run buildで何があったの?
最近いつもvueのいくつかの用法と文に対してまだ理解していないと感じて、そこでソースコードを引っ張って、自分のvueに対する理解を深めるために使うことを决めて、同时にvueは主にrollupを通じてパッケージのコンパイルを行って、それはwebpackに比べて更に軽くて、いいです、くだらないことは多く言わないで、始まりました!
上図に示すように、npm runbuildコマンドを実行するときは、まずpackage.jsonはそれをnode build/buildと解析する.js、このディレクトリを実行して、このディレクトリが何なのか見てみましょう.
コードを理解するのが難しい場合は、ファイルコードの下に整理されます!
直接build/buildに入ります.jsシールコード!
コードの解析を開始します
最初の2行は主にいくつかのモジュールを導入し、distファイルの判断は、注釈を通じて、きっと理解できると信じています.
let builds = require('./config').getAllBuilds()
次にこのbuildsが何なのか見てみましょう.まずconfigフォルダの下のコードを見てみましょう.
JavaScriptの例:
次に、最もパッケージ化されたコンパイル全体を整理します.
ビルドファイルを実行すると、モジュールを導入すると、./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をコンパイルし、対応するファイルを生成します.
このように全体のコンパイルの過程は実行し終わって、役に立つと思って、気をつけましょう!
最近いつも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をコンパイルし、対応するファイルを生成します.
このように全体のコンパイルの過程は実行し終わって、役に立つと思って、気をつけましょう!