vue中npm run build打包編譯的一系列操作
阿新 • • 發佈:2018-12-09
從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目錄,放置編譯打包後的檔案,這將是未來用在生產環境的包。