'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') 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') // cdn 引入 let externalModules = {} //cdn 配置 let externalConfig = [] if (process.env.NODE_ENV === 'production') { //生产环境 externalModules = { vue: 'Vue', 'vue-router': 'VueRouter', vuex: 'Vuex', axios: 'axios', 'element-ui': 'element-ui', echarts: 'echarts', highlight: 'hljs', } externalConfig = [ {js: 'https://cdn.jsdelivr.net/npm/vue@2.5.2/dist/vue.js', css: ''}, { js: 'https://cdn.bootcdn.net/ajax/libs/vue-router/3.0.1/vue-router.min.js', css: '', }, {js: 'https://unpkg.com/axios/dist/axios.min.js', css: ''}, {js: 'https://cdn.bootcss.com/vuex/3.6.2/vuex.min.js', css: ''}, { js: 'https://unpkg.com/element-ui/lib/index.js', css: 'https://unpkg.com/element-ui/lib/theme-chalk/index.css', }, { js: 'https://cdn.jsdelivr.net/npm/echarts@5.3.3/dist/echarts.min.js', css: '', }, { js: 'https://cdn.bootcdn.net/ajax/libs/highlight.js/11.6.0/highlight.min.js', css: '', }, { js: '', css: 'https://cdn.bootcdn.net/ajax/libs/github-markdown-css/5.1.0/github-markdown-light.min.css', }, { js: '', css: 'https://cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.css', }, ] } const webpackConfig = merge(baseWebpackConfig, { externals: externalModules, //打包忽略 module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true, }), }, devtool: config.build.productionSourceMap ? config.build.devtool : false, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'), }, plugins: [ // 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, }), // extract css into its own file 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({ 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', cdnConfig: externalConfig, // cdn配置 onlyCss: true, //dev下只加载css }), // 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 myblog_static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../myblog_static'), to: config.build.assetsSubDirectory, ignore: ['.*'], }, ]), ], }) if (config.build.productionGzip) { const CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push( new CompressionWebpackPlugin({ filename: '[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()) } if (config.build.isIgnoreLogs) { const UglifyJsPlugin = require('uglifyjs-webpack-plugin') let optimization = [ new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false, drop_debugger: true, //去掉debugger drop_console: true, // 去掉console pure_funcs: ['console.log'], // 移除console }, }, sourceMap: config.build.productionSourceMap, parallel: true, }), ] webpackConfig.plugins.push(...optimization) } module.exports = webpackConfig