@wibetter/akfun
Version:
前端脚手架:支持Vue技术栈和react技术栈
154 lines (142 loc) • 6.26 kB
JavaScript
const fs = require('fs');
const path = require('path');
const { merge } = require('webpack-merge');
const CopyWebpackPlugin = require('copy-webpack-plugin');
// const ExtractTextPlugin = require('extract-text-webpack-plugin'); // 不支持webpack4.0
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 替换extract-text-webpack-plugin
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const CompressionWebpackPlugin = require('compression-webpack-plugin');
const utils = require('./loaderUtils');
const { resolve } = require('../utils/pathUtils'); // 统一路径解析
const entrys2htmlWebpackPlugin = require('../utils/entrys2htmlWebpackPlugin');
// 引入当前项目配置文件
const projectConfig = require('../config/index');
const getBaseWebpackConfig = require('./webpack.base.conf');
module.exports = (akfunConfig) => {
let config = akfunConfig || projectConfig; // 默认使用执行命令目录下的配置数据
const curEnvConfig = config.build || {}; // 当前执行环境配置
// 获取webpack基本配置
const baseWebpackConfig = getBaseWebpackConfig(curEnvConfig, config);
// 获取页面模板地址
let curHtmlTemplate = path.resolve(__dirname, '../initData/template/index.html');
if (config.webpack.template) {
curHtmlTemplate = config.webpack.template; // akfun.config.js中的webpack配置
}
let curTarget = ['web', 'es5'];
if (config.webpack.target) {
curTarget = config.webpack.target; // akfun.config.js中的webpack配置
}
const webpackProdConfig = merge(baseWebpackConfig, {
target: curTarget,
mode: curEnvConfig.NODE_ENV, // production 模式,会启动UglifyJsPlugin服务
/*
内置变量列表:
id: chunk的唯一标识,从0开始;
name: chunk的名称;
hash: chunk的唯一标识的Hash值;
chunkhash: chunk内容的Hash值;
其中hash和chunkhash的长度是可以指定的,[hash:8]代表取8位的Hash值,默认是20位。
*/
output: {
path: curEnvConfig.assetsRoot, // 输出文件的存放在本地的目录
publicPath: curEnvConfig.assetsPublicPath, // 引用地址:配置发布到线上资源的URL前缀
filename: utils.assetsPath('scripts/chunk/[name].[contenthash:8].js'),
chunkFilename: utils.assetsPath('scripts/chunk/[name].[contenthash:8].js')
},
module: {
rules: utils.styleLoaders({
sourceMap: curEnvConfig.productionSourceMap,
environment: 'prod',
cssLoaderUrl: config.webpack.cssLoaderUrl,
cssLoaderUrlDir: config.webpack.cssLoaderUrlDir,
cssLoaderOption: config.webpack.cssLoaderOption, // 用于自定义css-loader配置项(优先级最高)
})
},
devtool: curEnvConfig.productionSourceMap ? curEnvConfig.devtool || 'source-map' : false, // 线上生成环境
optimization: {
chunkIds: 'deterministic', // 在不同的编译中不变的短数字 id。有益于长期缓存。在生产模式中会默认开启。
emitOnErrors: true,
splitChunks: {
cacheGroups: {
defaultVendors: {
// 4.0: vendors
test: /node_modules\/(.*)/,
name: 'vendor',
chunks: 'initial',
reuseExistingChunk: true
},
common: {
name: 'common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
},
minimize: true,
minimizer: [
// For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
`...`,
new CssMinimizerPlugin()
]
},
plugins: [
new MiniCssExtractPlugin({
filename: utils.assetsPath('css/[name].[contenthash:8].css'),
ignoreOrder: false // Enable to remove warnings about conflicting order
})
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
/**
* 该插件可以接收以下选项(它们都是可选的):
* assetNameRegExp:表示应优化的资产的名称的正则表达式\最小化,默认为 /\.css$/g
* cssProcessor:用于优化\最小化CSS的CSS处理器,默认为cssnano。
* 这应该是cssnano.process接口之后的一个函数(接收一个CSS和options参数并返回一个Promise)。
* cssProcessorOptions:传递给cssProcessor的选项,默认为 {}
* canPrint:一个布尔值,指示插件是否可以将消息打印到控制台,默认为 true
*/
]
});
// 使用用户自定义的多入口配置,生产对应的多页面多模板
const htmlWebpackPluginList = entrys2htmlWebpackPlugin(webpackProdConfig.entry, curHtmlTemplate);
htmlWebpackPluginList.forEach((htmlWebpackPlugin) => {
webpackProdConfig.plugins.push(htmlWebpackPlugin);
});
// 判断是否有public目录,如果有需要转移到dist目录下
if (fs.existsSync(resolve('public'))) {
// copy custom public assets
webpackProdConfig.plugins.push(
new CopyWebpackPlugin({
patterns: [
{
from: resolve('public'), // 从这里拷贝
to: curEnvConfig.assetsSubDirectory // 将根目录下的public内的资源复制到指定文件夹
}
]
})
);
}
// 是否要进行压缩工作
if (curEnvConfig.productionGzip) {
webpackProdConfig.plugins.push(
new CompressionWebpackPlugin({
test: new RegExp(`\\.(${curEnvConfig.productionGzipExtensions.join('|')})$`),
filename: '[path].gz[query]',
algorithm: 'gzip',
threshold: 240,
minRatio: 0.8
})
);
}
// 判断当前环境是否有自定义plugins
if (curEnvConfig.plugins && Array.isArray(curEnvConfig.plugins)) {
// 添加自定义webpack插件
webpackProdConfig.plugins.push(...curEnvConfig.plugins);
}
if (curEnvConfig.bundleAnalyzerReport) {
webpackProdConfig.plugins.push(new BundleAnalyzerPlugin());
}
return webpackProdConfig;
};