const path = require('path');
const getEntry = require('./getEntry');
const webpack = require('webpack');
const webpackProdConfig = require('./webpack.prod.config.js');
const hammer = require('./hammer');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = require('../new-config.json');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const getVersion = require('./version');
const dependjsConf = require('../dependjs.json');
Object.assign(config, dependjsConf);
// 项目根目录
const projectPath = path.join(__dirname, '../');
// 输入参数,hrhi hrwa 什么的
const inputParam = [].slice.call(process.argv, 2);
let runType = inputParam[0];
if (runType === 'patch') {
inputParam.shift();
}
// 参数拼装的正则,要是没有参数这个值为false
// 页面入口对象和模版集合
let entry = getEntry();
// 模块入口对象
let libEntry = getEntry('lib');
// 入口对象
let entryMap = entry.entry;
// 自定义模版map
let entryTemplateMap = entry.template;
// 模块入口对象
let libEntryMap = libEntry.entry;
//过滤lib
let libEntryMapModule = {};
if (inputParam && inputParam.length > 0) {
let reg = new RegExp(`^(${inputParam})`);
for (let key in libEntryMap) {
if (reg.test(key)) {
libEntryMapModule[key] = libEntryMap[key];
}
}
} else {
libEntryMapModule = libEntryMap;
}
if (Object.keys(libEntryMapModule).length <= 0) {
libEntryMapModule = libEntryMap;
}
// 临时中间变量,用于过滤参数选择的入口
let midTrans = {};
// 通过过滤入口的key值,找到对应的map
Object.keys(entryMap).map((key) => {
if (inputParam && inputParam.length > 0) {
let ifCurrentKeyIsEntry = false;
for (let p of inputParam) {
if (key.includes(p)) {
ifCurrentKeyIsEntry = true;
break;
}
}
if (ifCurrentKeyIsEntry) {
midTrans[key] = entryMap[key];
}
} else {
midTrans[key] = entryMap[key];
}
});
// console.log('==== 入口 ====');
if (Object.keys(midTrans).length > 0) {
entryMap = midTrans;
}
// 拥有页面的入口的js对应的插件列表
let pagePlugins = [...webpackProdConfig.plugins];
// 没有页面的入口的js的对应的插件列表
let libPlugins = [...webpackProdConfig.plugins];
// 之后会切割入口文件以提升速度,这个变量就是存储切割后的入口数组
let entryList = [];
// 切割入口文件的时候用到的临时中转变量
let cache = {};
// 拿到所有入口的key值
let entryMapKeysList = Object.keys(entryMap);
// 所有的编译花费的时间数组
let costTime = [];
// 只运行一次的行为标志,主要用在了复制和clean插件上
let firstTime = true;
let allStartTime = Date.now();
// 通过遍历,将数据量很大的入口对象,切割成每30个入口文件为一个的数组
entryMapKeysList.map((key, index) => {
cache[key] = entryMap[key];
if (index % 20 === 0) {
entryList.push(cache);
cache = {};
return;
} else if (entryMapKeysList.length - 1 === index) {
entryList.push(cache);
}
});
// 运行链式的编译
runList(entryList.shift());
// 编译没有模板文件
function libCompile() {
let arr = [];
config['copy'].map((key, index) => {
if (inputParam && inputParam.length > 0) {
for (let p of inputParam) {
if (key['from'].includes(p)) {
hammer.isFileExist(key.from) && arr.push(key);
break;
}
}
} else {
if (!key['exclude']) {
hammer.isFileExist(key.from) && arr.push(key);
}
}
});
// 复制操作是在模块编译这里进行
libPlugins.push(new CopyPlugin(arr));
if (Object.keys(libEntryMapModule).length <= 0) {
console.log('总耗时:', Date.now() - allStartTime);
return;
}
webpackProdConfig.entry = libEntryMapModule;
webpackProdConfig.plugins = libPlugins;
webpackProdConfig.output.filename = '[name].js';
webpack(webpackProdConfig, (err, stats) => {
if (err) {
console.log(err);
// throw new Error(err);
return;
}
console.log(stats.toString({
chunks: false, // Makes the build much quieter
colors: true // Shows colors in the console
}));
let t = stats.endTime - stats.startTime;
costTime.push(t);
console.log('总耗时:', Date.now() - allStartTime);
});
}
// 链式运行入口组
function runList(entryMap) {
compile(entryMap).then(() => {
let entry = entryList.shift();
if (entry) {
runList(entry);
} else if (runType !== 'patch') {
libCompile();
}
});
}
// 根据一个map执行编译
function compile(entryMap) {
return new Promise((resolve, reject) => {
let currentPlugin = [...pagePlugins];
if (firstTime) {
firstTime = false;
currentPlugin.unshift(
new CleanWebpackPlugin(['dist'], {
root: path.join(__dirname, '../'),
verbose: true,
dry: false
})
);
}
// 根据入口配置添加html插件
/*let configjs = ''; //额外配置的js文件
let configcss = ''; //额外配置的css文件*/
let externals = {};
// dependjs: 依赖的js文件配置
/*if (Array.isArray(config.dependjs)) {
configjs += config.dependjs.map(src => {
let moduleName = /(?:\.\.\/)*([^\.]*)\.js/.exec(src);
if (moduleName && moduleName[1]) {
externals[moduleName[1]] = moduleName[1];
}
return ``;
}).join('');
}*/
//优化依赖js方法,只有用到的时候才去添加
// dependModuleName: 依赖的模块名
if (Array.isArray(config.dependModuleName)) {
// 打包时排除
config.dependModuleName.forEach(item => (externals[`${item}`] = `${item}/index`));
}
// dependcss: 依赖的css文件配置
/*if (Array.isArray(config.dependcss)) {
configcss += config.dependcss
.map(item => ``)
.join('');
}*/
Object.keys(entryMap).map((key) => {
const cmodule = key.split("/")[0];
// const buildInfo = getVersion('src/' + cmodule);
const filePath = key.substr(0, key.length - 11);
let configjs = getConfigJs(filePath); //额外配置的js文件
let configcss = getConfigCss(filePath); //额外配置的css文件
let htmlWebpackOption = {
filename: `${key}.html`,
template: path.join(projectPath, config['default-template']),
chunks: [key],
inject: true,
templateParameters: {
buildInfo: '',
configjs: configjs, //为模板添加js
configcss: configcss //为模板添加css
}
};
if (entryTemplateMap[key]) {
htmlWebpackOption.template = path.join(projectPath, entryTemplateMap[key]);
}
currentPlugin.push(new HtmlWebpackPlugin(htmlWebpackOption));
});
webpackProdConfig.entry = entryMap;
webpackProdConfig.plugins = currentPlugin;
Object.assign(webpackProdConfig.externals, externals);
webpack(webpackProdConfig, (err, stats) => {
console.log(stats.toString());
if (err) {
console.log(err);
// throw new Error(err);
reject();
// return;
}
console.log(stats.toString({
chunks: false, // Makes the build much quieter
colors: true // Shows colors in the console
}));
let t = stats.endTime - stats.startTime;
costTime.push(t);
console.log('耗时:', t);
resolve();
});
});
}
/*
* 引用js优化,如果需要只在特定的html中引入uap的js,可以放开这里的代码
* */
function getConfigJs(filePath) {
// dependjs: 依赖的js文件配置
let configjs = '';
if (config.dependjs && Array.isArray(config.dependjs[filePath])) {
config.dependjs[filePath].forEach(file => {
configjs += ``;
})
}
if (Array.isArray(config.report) && config.report.includes(filePath)) {
configjs += ``;
configjs += ``;
}
if (Array.isArray(config.wpsconfig) && config.wpsconfig.includes(filePath)) {
configjs += ``;
}
return configjs;
}
function getConfigCss(filePath) {
// dependcss: 依赖的css文件配置
let configcss = '';
if (Array.isArray(config.dependcss)) {
configcss += config.dependcss
.map(item => ``)
.join('');
}
if (Array.isArray(config.report) && config.report.includes(filePath)) {
configcss += ``;
configcss += ``;
}
return configcss;
}