/* * @Author: liyxt * @Date: 2019-04-23 09:37:04 * @LastEditors: Please set LastEditors * @LastEditTime: 2024-01-09 16:00:47 * @Description: file content */ const { CleanWebpackPlugin } = require('clean-webpack-plugin'); const glob = require('glob'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const fs = require('fs'); const webpack = require('webpack'); const configJSON = require('../config.json'); const fileRules = require('./fileRules'); const { resolve, join } = require('path'); module.exports = function buildEntry({ buildPath, buildWithoutHTML, hash, mode, client, fse, srcDir = configJSON.srcDir || 'src', patchList }) { fse = fse === 'true' || fse === true || false; Array.isArray(buildWithoutHTML) && buildWithoutHTML.unshift('refer'); let projects = [], plugins = [], entries = {}, externals = {}, lowCodeEntries = [], rules=[]; // 遍历src下的js (function(callback) { if (Array.isArray(buildPath)) { buildPath.forEach(_buildPath => { callback(_buildPath); }); } else { callback(buildPath); } })(function(buildPath) { getFiles(buildPath); }); if (patchList) { let copyList = getCopyList(patchList); copyList.forEach((path) => { if(fs.existsSync(path)) { plugins.push( new CopyWebpackPlugin([ // {output}/to/file.txt { from: path, to: './' + path.match(/.*src\/(.*)/)[1] } ]) );} }) } else { projects.forEach(e => { if (e === 'uapbd') { // guozhq让弄的,供应链特殊 fs.existsSync(`./${srcDir}/uapbd/scmbase/public`) && plugins.push( new CopyWebpackPlugin([{ from: `./${srcDir}/uapbd/scmbase/public`, to: `./uapbd/scmbase/public` }]) ); // wanghxm让弄的,hr特殊 fs.existsSync(`./${srcDir}/uapbd/hrbase/public`) && plugins.push( new CopyWebpackPlugin([{ from: `./${srcDir}/uapbd/hrbase/public`, to: `./uapbd/hrbase/public` }]) ); } fs.existsSync(`./${srcDir}/${e}/public`) && plugins.push( new CopyWebpackPlugin([ // {output}/to/file.txt { from: `./${srcDir}/${e}/public`, to: `./${e}/public` } ]) ); }); } function getProjectConfigByPath(path) { let project = path.split('/')[2]; let configPath = `./${srcDir}/${project}/config.json`; let isExists = fs.existsSync(configPath); if (isExists) { plugins.push( new CopyWebpackPlugin([{ from: `./${srcDir}/${project}/config.json`, to: `./${project}/config.json` }]) ); return require('.' + configPath); } return {}; } function getFiles(buildPath) { let {buildEntryPath:projectBuildEntryPath=[]} = getProjectConfigByPath(buildPath); glob.sync(buildPath).forEach(path => { // path ---为加载的每个index.js文件:./src/reva_demo/module/apply/list/index.js // chunk = 节点+list/card: reva_demo/module/apply/list // 原来移动和pc的构建判断比较严格,2207之后应差异化不大了,这里先把判断短路,看一下后面会有什么问题,没问题的话就统一改掉 if ( (client === 'mobile' && path.includes('/mobile_')) || (client !== 'mobile' && !path.includes('/mobile_')) ||true ) { // 移动端 || web端 let chunk = path.split(`./${srcDir}/`)[1].split('/index.js')[0], project = chunk.split('/')[0]; // reva_demo //把src自定义命名下的文件层级减掉,更改第二层级,把领域名改为 extend_领域名 by bbqin if (fse) { let chunkarr = chunk.split('/'); chunkarr[0] = 'NCCExtend'; chunkarr[1] = `extend_${chunkarr[1]}`; chunk = chunkarr.join('/'); } projects.includes(project) || projects.push(project); // 生成webpack.config.js的入口 let configJSONPath = `./${srcDir}/` + chunk + '/config.json', isExists = fs.existsSync(configJSONPath), _hash, isLowCodeEntry = false; if (isExists) { // 特殊处理的 let { hash, isLowCode, maxChunks } = require('.' + configJSONPath); // maxChunks,打包生成的最大chunks数量 if (typeof maxChunks === 'number' && maxChunks > 0) { plugins.push(new webpack.optimize.LimitChunkCountPlugin({maxChunks})) } _hash = isLowCode? false : hash; if(isLowCode){ lowCodeEntries.push(chunk); } } if (hash === 'false') { hash = false; } else if (hash === 'true') { hash = true; } let _chunk = ('/' + chunk + '/').toLowerCase(); if (mode === 'development') { entries[`${chunk}/index`] = path; } else { if (hash) { // 筛选出带hash的 if (_hash) { // config.json里的hash优先级高 entries[`${chunk}/index`] = path; } else if (_hash !== false) { // 非参照页面生成hash if(!( _chunk.includes('/refer/') || _chunk.includes('/ref/') || _chunk.includes('/refers/') || _chunk.includes('/mobile_refer/') || fse )){ if(projectBuildEntryPath.length>0){ projectBuildEntryPath.includes(path) && (entries[`${chunk}/index`] = path); }else{ //后续增加强判断,如果没有配config.json就不出盘 entries[`${chunk}/index`] = path; } } } } else { // 筛选出不带hash的 if (_hash === false) { // config.json里的hash优先级高 entries[`${chunk}/index`] = path; } else if (_hash !== true) { // 参照页面不生成hash (_chunk.includes('/refer/') || _chunk.includes('/ref/') || _chunk.includes('/refers/') || _chunk.includes('/mobile_refer/') || _hash === false || fse) && (entries[`${chunk}/index`] = path); } } } // buildWithoutHTML中的页面不生成html if (entries[`${chunk}/index`]) { let templatePath = client === 'mobile' ? './template/mobileTemplate.html' : './template/index.html'; let configjs = ''; //额外配置的js文件 let configcss = ''; //额外配置的css文件 if (isExists) { let { template, output, dependjs, dependcss, dependModuleName, report, echarts, prodProxy, isLowCode, importParseLayout, specialExternals={}, packages = [], schema, copyFile, } = require('.' + configJSONPath); isLowCodeEntry = isLowCode; // template: HTML模板路径 if (template) { templatePath = template; } //低代码模式引用新的模板 if(isLowCodeEntry){ templatePath = "./template/lowcodeTemplate.html"; } // output: 单独输出的文件配置 if (output) { entries[`${output}/index`] = path; } if (schema) { entries[`${chunk}/index_schema`] = path.replace('index.js', 'index.schema.js'); } if (copyFile) { plugins.push( new CopyWebpackPlugin(copyFile.map(({ from, to }) => { return { from: resolve(path, '../', from), to: join(chunk, to) } })) ) } // report: 报表依赖 if (report) { configjs += ``; configjs += ``; configcss += ``; configcss += ``; } if (echarts) { // platform下已经没有echarts文件,避免404报错 // configjs += ``; } //importParseLayout :低代码解析组件 if (importParseLayout) { configjs += ``; } // dependjs: 依赖的js文件配置 if (Array.isArray(dependjs)) { configjs += dependjs.map(src => { let moduleName = /(?:\.\.\/)*([^\.]*)\.js/.exec(src); if (moduleName && moduleName[1]) { externals[moduleName[1]] = moduleName[1]; } return ``; }).join(''); } // dependcss: 依赖的css文件配置 if (Array.isArray(dependcss)) { configcss += dependcss .map(item => ``) .join(''); } // dependModuleName: 依赖的模块名 if (Array.isArray(dependModuleName)) { // 打包时排除 dependModuleName.forEach(item => (externals[`${item}`] = `${item}/index`)); } if (Array.isArray(packages)) { packages.forEach(({ name, src, var: root }) => { if (!Array.isArray(src)) { src = [src] } src.forEach((e) => { if (/.js$/.test(e)) { configjs += ``; } else if (/.css$/.test(e)) { configcss += `` } }) externals[name] = root || name; }) } // specialExternals: 特殊的排除 externals = Object.assign(externals,specialExternals); plugins.push( new webpack.DefinePlugin({ PROD_PROXY: JSON.stringify((mode !== 'development' && prodProxy) || '') }) ); } if ((!(buildWithoutHTML || []).some(e => path.includes(e)))) { const htmlConf = { filename: `${chunk}/index.html`, // 生成的html文件名,可加目录/.../.../index.html template: `${templatePath}`, // 模板html路径 inject: true, //允许插件修改哪些内容,包括head与body chunks: [`${chunk}/index`], // 生成的html文件引入哪些js,不传的话引入所有js cache: true, templateParameters: { configjs: configjs, //为模板添加js configcss: configcss, //为模板添加css prefix: chunk.split('/').join('_') //css前缀 } }; if(isLowCodeEntry){ htmlConf.chunks = []; } plugins.push(new HtmlWebpackPlugin(htmlConf)); //rules = fileRules({ cssSandbox: true, chunk }); } } } }); } let cleanOnceBeforeBuildPatterns = Object.values(entries).map(e => e.replace('index.js', '').replace(`./${srcDir}/`, '')); plugins.push( new CleanWebpackPlugin({ cleanOnceBeforeBuildPatterns, cleanAfterEveryBuildPatterns: [], verbose: true }) ); return { plugins, entries, externals, lowCodeEntries, rules, }; }; function getCopyList(patchList) { if (!patchList) { return []; } let content = fs.readFileSync(patchList, { encoding: 'utf-8' }); // content.replace('\r', ''); let lines = content.split(/\r?\n/), group = {}, currentGroup = '前端'; lines.forEach((line) => { if (/\*{3}/.test(line)) { currentGroup = line; } else { group[currentGroup] = group[currentGroup] || []; line && group[currentGroup].push(line); } }) let copyList = []; Object.entries(group).forEach(([name, lines]) => { if (name.includes('前端')) { let [, module] = name.match(/\*{3}\s([^|]*)\|/) || []; lines.forEach((line) => { let [type, path1, path2] = line.split(/\s+/), path = ''; switch (type) { case 'A': case 'M': path = path1; break; case 'R': path = path2; break; default: break; } if (path && !path.includes(module)) { path = `src/${module}/${path}`; } if (path.includes(`${module}/public`) && !/\.js$|\.less$|\.css$/.test(path)) { copyList.push(path); } }) } }) return copyList; }