1. 程式人生 > >vue中npm run build打包編譯的一系列操作

vue中npm run build打包編譯的一系列操作

從package.json 中可以看出,npm run build,其實是執行了 node build/build.js,我們在build資料夾中找到build.js,build主要的工作是:檢測node和npm版本,刪除dist包,webpack構建打包,在終端輸出構建資訊並結束,如果報錯,則輸出報錯資訊。  

'use strict'

require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')// 在終端顯示的旋轉器外掛
const rm = require('rimraf')// 用於刪除資料夾
const path = require('path')
const chalk = require('chalk')// 終端文字顏色外掛
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
// 刪除dist資料夾,之後webpack打包
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()

if (err) throw err

process.stdout.write(stats.toString({

colors: true,

modules: false,

children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.

chunks: false,

chunkModules: false

}) + '\n\n')

if (stats.hasErrors()) {

console.log(chalk.red(' Build failed with errors.\n'))

process.exit(1)

}

console.log(chalk.cyan(' Build complete.\n'))

console.log(chalk.yellow(

' Tip: built files are meant to be served over an HTTP server.\n' +

' Opening index.html over file:// won\'t work.\n'

))

})

})

build.js用到了webpack.prod.conf.js,他與webpack.base.conf.js merge之後,作為webpack配置檔案,我們再看看webpack.prod.conf.js,主要做的工作是: 1.提取webpack生成的bundle中的文字,到特定的檔案,使得css,js檔案與webpack輸出的bundle分離。

2.合併基本的webpack配置

3.配置webpack的輸出,包括輸出路徑,檔名格式。

4.配置webpack外掛,包括醜化程式碼。

5.gzip下引入compression外掛進行壓縮。

'use strict'

const path = require('path')

const utils = require('./utils')

const webpack = require('webpack')

const config = require('../config')

const merge = require('webpack-merge')

const baseWebpackConfig = require('./webpack.base.conf')

const CopyWebpackPlugin = require('copy-webpack-plugin')

const HtmlWebpackPlugin = require('html-webpack-plugin')

// 用於從webpack生成的bundle中提取文字到特定檔案中的外掛

// 可以抽取出css,js檔案將其與webpack輸出的bundle分離

const ExtractTextPlugin = require('extract-text-webpack-plugin')

const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

const UglifyJsPlugin = require('uglifyjs-webpack-plugin')



const env = process.env.NODE_ENV === 'testing'

? require('../config/test.env')

: require('../config/prod.env')

// 合併基礎的webpack配置

const webpackConfig = merge(baseWebpackConfig, {

module: {

rules: utils.styleLoaders({

sourceMap: config.build.productionSourceMap,

extract: true,

usePostCSS: true

})

},

devtool: config.build.productionSourceMap ? config.build.devtool : false,

// 配置webpack輸出的目錄,及檔案命名規則

output: {

path: config.build.assetsRoot,

filename: utils.assetsPath("js/[name].[chunkhash].js"),

chunkFilename: utils.assetsPath("js/[id].[chunkhash].js")

},

plugins: [

// webpack外掛配置

// http://vuejs.github.io/vue-loader/en/workflow/production.html

new webpack.DefinePlugin({

"process.env": env

}),

// 醜化程式碼

new UglifyJsPlugin({

uglifyOptions: {

compress: {

warnings: false

}

},

sourceMap: config.build.productionSourceMap,

parallel: true

}),

// // 抽離css檔案到單獨的檔案

new ExtractTextPlugin({

filename: utils.assetsPath("css/[name].[contenthash].css"),

// Setting the following option to `false` will not extract CSS from codesplit chunks.

// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.

// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,

// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110

allChunks: true

}),

// Compress extracted CSS. We are using this plugin so that possible

// duplicated CSS from different components can be deduped.

new OptimizeCSSPlugin({

cssProcessorOptions: config.build.productionSourceMap

? { safe: true, map: { inline: false } }

: { safe: true }

}),

// generate dist index.html with correct asset hash for caching.

// you can customize output by editing /index.html

// see https://github.com/ampedandwired/html-webpack-plugin

new HtmlWebpackPlugin({

// 生成並注入index.html

filename:

process.env.NODE_ENV === "testing" ? "index.html" : config.build.index,

template: "index.html",

inject: true,

minify: {

removeComments: true,

collapseWhitespace: true,

removeAttributeQuotes: true

// more options:

// https://github.com/kangax/html-minifier#options-quick-reference

},

// necessary to consistently work with multiple chunks via CommonsChunkPlugin

chunksSortMode: "dependency"

}),

// keep module.id stable when vendor modules does not change

new webpack.HashedModuleIdsPlugin(),

// enable scope hoisting

new webpack.optimize.ModuleConcatenationPlugin(),

// split vendor js into its own file

new webpack.optimize.CommonsChunkPlugin({

name: "vendor",

minChunks(module) {

// any required modules inside node_modules are extracted to vendor

return (

module.resource &&

/\.js$/.test(module.resource) &&

module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0

);

}

}),

// extract webpack runtime and module manifest to its own file in order to

// prevent vendor hash from being updated whenever app bundle is updated

new webpack.optimize.CommonsChunkPlugin({

name: "manifest",

minChunks: Infinity

}),

// This instance extracts shared chunks from code splitted chunks and bundles them

// in a separate chunk, similar to the vendor chunk

// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk

new webpack.optimize.CommonsChunkPlugin({

name: "app",

async: "vendor-async",

children: true,

minChunks: 3

}),


// copy custom static assets

new CopyWebpackPlugin([

{

from: path.resolve(__dirname, "../static"),

to: config.build.assetsSubDirectory,

ignore: [".*"]

}

])

]

});

// gzip模式下需要引入compression外掛進行壓縮

if (config.build.productionGzip) {

const CompressionWebpackPlugin = require('compression-webpack-plugin')



webpackConfig.plugins.push(

new CompressionWebpackPlugin({

asset: '[path].gz[query]',

algorithm: 'gzip',

test: new RegExp(

'\\.(' +

config.build.productionGzipExtensions.join('|') +

')$'

),

threshold: 10240,

minRatio: 0.8

})

)

}
if (config.build.bundleAnalyzerReport) {

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

webpackConfig.plugins.push(new BundleAnalyzerPlugin())

}


module.exports = webpackConfig

總結:執行npm run dev或者npm run start,實際是在node環境執行build/dev-server.js, dev-server.js會去拿到config中的埠等配置,通過express起一個服務,通過外掛自動開啟瀏覽器,載入webpack編譯後放在記憶體的bundle。

執行npm run build,實際上執行了build/build.js,通過webpack的一系列配置及外掛,將檔案打包合併醜化,並建立dist目錄,放置編譯打包後的檔案,這將是未來用在生產環境的包。