const path = require('path') const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const ExtractTextPlugin = require('extract-text-webpack-plugin') const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') const utils = require('./utils') const packageConfig = require('../package.json') // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin //路径转换 function resolve(dir) { return path.join(__dirname, '..', dir) } //语法验证 const createLintingRule = () => ({ test: /\.(js|vue|dtvevt)$/, loader: 'eslint-loader', enforce: 'pre', include: [resolve('src'), resolve('test')], options: { formatter: require('eslint-friendly-formatter'), emitWarning: !config.dev.showEslintErrorsInOverlay } }) const useEslint = true; const projectName = packageConfig.name||'project'; module.exports = { //指定目录,默认的值就是项目的根目录 context: resolve(projectName), //编译入口 String||Array // entry: '', //动态多入门文件时 entry() { // 初始化入口配置 const entry = {} // 所有模块的列表 const moduleToBuild = require('./module-conf').getModuleToBuild() || [] // 根据传入的待打包目录名称,构建多入口配置 for (let module of moduleToBuild) { // entry[module] = `${module}/index.js` let name = module.replace(/\//gi, '_'); entry[name] = `${module}/index.js` } return entry }, //输出路径 output: { path: resolve('dist'), filename: '[name].js', //指定打包后的资源目录 相对于dist 下 publicPath: './' }, // output: { // filename:'static/js/[name].[chunkhash].js', // chunkFilename: 'static/js/[id].[chunkhash].js' // }, //如何寻找模块所对应的文件 resolve: { // 配置省略文件路径后缀名,引入文件的时候可以不用写文件的后缀名 extensions: ['.js', '.vue', '.json'], //指定引用别名 alias: { 'vue$': 'vue/dist/vue.esm.js', // '@': resolve('src'), } }, //排除不打包 externals: { // jquery: "jQuery", }, //解析模块的规则 module: { rules: [ ...(useEslint ? [createLintingRule()] : []), ...(utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true })), { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, { test: /\.js$/, loader: 'babel-loader?cacheDirectory', //需要被loader 处理的文件或文件夹 include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')], //不需要被loader 处理的文件或文件夹 exclude: [] }, { test: /\.svg$/, loader: 'svg-sprite-loader', include: [resolve('src/icons')], options: { symbolId: 'icon-[name]' } }, { test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', // exclude: [resolve('src/icons')], options: { limit: 10000, name: 'static/img/[name].[hash:7].[ext]' } }, { test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'static/media/[name].[hash:7].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000, name: 'static/fonts/[name].[hash:7].[ext]' } } ] }, devtool: '#source-map', plugins: [ //注入全局变量的插件,通常使用该插件来判别代码运行的环境变量 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"', ENV_CONFIG: '"prod"', BASE_API: '"https://api-prod"' } }), //webpack 4之前的版本是通过webpack.optimize.CommonsChunkPlugin来压缩js, //webpack 4版本之后被移除了,使用config.optimization.splitChunks来代替 //用来缩小(压缩优化)js文件 new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: false, parallel: true }), // 将css提取到自己的文件中 new ExtractTextPlugin({ filename: 'static/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. // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 allChunks: false, }), // 压缩提取的CSS。我们使用这个插件是为了来自不同组件的重复CSS可以被删除。 new OptimizeCSSPlugin({ //开发环境 // cssProcessorOptions:{ // safe: true, map: { inline: false } // }, //打包生产 cssProcessorOptions: { safe: true } }), // keep module.id stable when vender 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 }), //提取引用最小3次的公共包 // 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 }), // split echarts into its own file new webpack.optimize.CommonsChunkPlugin({ async: 'echarts', minChunks(module) { var context = module.context; return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0); } }), // split xlsx into its own file new webpack.optimize.CommonsChunkPlugin({ async: 'xlsx', minChunks(module) { var context = module.context; return context && (context.indexOf('xlsx') >= 0); } }), // split codemirror into its own file new webpack.optimize.CommonsChunkPlugin({ async: 'codemirror', minChunks(module) { var context = module.context; return context && (context.indexOf('codemirror') >= 0); } }), // copy custom static assets new CopyWebpackPlugin([ { from: resolve('static'), to: 'static', ignore: ['.*'] } ]), // 打包后,对包进行大小分析 // new BundleAnalyzerPlugin() ], }