UNPKG

@wbi/cli-service

Version:

local service for wb-cli projects

281 lines (258 loc) 9.49 kB
/** * Created by Administrator on 2019/2/7. * 一些辅助方法 */ const fs = require('fs') const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const glob = require('glob') const rm = require('rimraf') // resolve项目根目录地址 const resolve = str => path.join(process.cwd(), str) const wbConfig = require(resolve('./wb.config')) const config = wbConfig.private exports.resolve = resolve exports.wbConfig = wbConfig exports.privateConfig = config // 当前cli配置文件夹地址 exports.resolveConfig = str => path.join(__dirname, '../', 'config', str) // 获取生成模式下的的htmlPlugins exports.getHtmlPluginsInBuildList = function () { let htmlPlugins = [] // 模板继承扩展 if (wbConfig.extend) { const pages = parseExtend() createExtendPage(pages) } glob.sync('./src/*.pug').concat(glob.sync('./.tmp/*.pug')).forEach(file => { let key = file.match(/\.\/(src|\.tmp)\/(.*)\.pug/)[2] let isInWhiteList = true if (!config.buildAll && config.buildList.length) { isInWhiteList = config.buildList.some(function (page) { return page === key }) } isInWhiteList && htmlPlugins.push( new HtmlWebpackPlugin({ filename: key + '.html', template: file, multihtmlCache: true // 多页面时,用来解决热重载慢的问题 }) ) }) return htmlPlugins } // 获取开发模式下的的htmlPlugins exports.getHtmlPluginsInDevList = function () { let htmlPlugins = [] // 模板继承扩展 if (wbConfig.extend) { const pages = parseExtend() createExtendPage(pages) } glob.sync('./src/*.pug').concat(glob.sync('./.tmp/*.pug')).forEach(file => { let key = file.match(/\.\/(src|\.tmp)\/(.*)\.pug/)[2] let isInWhiteList = true if (!config.devAll && config.devList.length) { isInWhiteList = config.devList.some(function (page) { return page === key }) } isInWhiteList && htmlPlugins.push( new HtmlWebpackPlugin({ filename: key + '.html', template: file, multihtmlCache: true // 多页面时,用来解决热重载慢的问题 }) ) }) return htmlPlugins } // 解析模板继承的数据 // 解析之后会在extend数据的具体页面中增加 extendData 属性 const parseExtend = () => { const pages = {} Object.keys(wbConfig.extend.pages).forEach(pageName => { const page = wbConfig.extend.pages[pageName] let dataContent = fs.readFileSync(page.dataFile).toString() // src路径变量解析 const srcPath = '../src/' const staticPath = '' const commonStaticPath = '' // 所有站点路径变量解析 Object.keys(config.sitePath).forEach(pathKey => { global[pathKey] = config.sitePath[pathKey] }) eval(dataContent.replace(/.*-\r?\n/, '')) if (!page.replace) { page.replace = [/extendData.panels\[0\]\[0\]/g, 'extendData.panels[{index1}][{index2}]'] } pages[pageName] = {extendData, ...page} }) return pages } // 根据模板批量创建页面 // 创建的页面存放到根目录的 .tmp 文件夹下 const createExtendPage = pages => { const tmpPath = resolve('./.tmp') rm.sync(tmpPath) fs.mkdirSync(tmpPath) Object.keys(pages).forEach(pageName => { const page = pages[pageName] let templateContent = fs.readFileSync(page.template).toString() page.extendData.panels.forEach((data, index1) => { data.forEach((item, index2) => { let targetContent = templateContent.replace('extends layouts', 'extends ../src/layouts') let regTarget = page.replace[1].replace('{index1}', index1) regTarget = regTarget.replace('{index2}', index2) targetContent = targetContent.replace(page.replace[0], regTarget) fs.writeFileSync(path.join(tmpPath, `${item.pageName}.pug`), targetContent) }) }) }) } // 将二维数组拍平成一维数组 const flatten = arr => [].concat( ...arr.map(x => x) ) // 获取构建配置文件 exports.getConfigFiles = function () { return glob.sync(path.join(__dirname, './**/!(webpack.prod.config).*')).map(file => { return path.resolve(process.cwd(), file) }).concat([resolve('./wb.config.js'), resolve('./private.config.js')]) } // 获取静态资源路径 exports.getStaticPath = function (opts = {}) { let res = {} if (process.env.NODE_ENV === 'development') { res.staticPath = path.posix.join(opts.publicPath || wbConfig.publicPath.dev, 'static') res.commonStaticPath = path.posix.join(opts.publicPath || wbConfig.publicPath.dev, 'commonStatic') } else { const publicPath = opts.publicPath || wbConfig.publicPath.build if (publicPath.substring(0, 4) !== 'http') { res.staticPath = path.posix.join(publicPath, 'static') res.commonStaticPath = path.posix.join(publicPath, 'commonStatic') } else { res.staticPath = publicPath + 'static' res.commonStaticPath = publicPath + 'commonStatic' } } return res } // 解析静态资源,将{staticPath}、{commonStaticPath}替换成真实的资源路径 exports.parseStaticAssets = function (staticTemplate, staticPath, staticAssets = {}) { Object.keys(staticAssets).forEach(key => { const assets = staticAssets[key] assets.forEach((file, index) => { assets[index] = file.replace(staticTemplate, staticPath) }) }) return staticAssets } // 合并静态资源 exports.mergeStaticAssets = function ({type, staticTemplate, directory, modifyName, outPath, staticAssets, hash7}) { Object.keys(staticAssets).forEach(key => { let content = '' const assets = staticAssets[key] || [] assets.forEach(file => { content += fs.readFileSync(file.replace(staticTemplate, directory)) + '\n' }) if (assets.length) { fs.writeFileSync(`${outPath}/${type}/lib/vendor${modifyName}${hash7 ? '.' + hash7 : ''}.${key}`, content) } }) } // 修改main.scss的$staticPath路径 exports.modifyStyleStaticPath = function (staticPath, commonStaticPath) { const mainScssFile = resolve('./src/css/main.scss') let mainScss = fs.readFileSync(mainScssFile, 'utf8') let staticReg = /\$staticPath\s*:\s*'(.*)'/ let commonStaticReg = /\$commonStaticPath\s*:\s*'(.*)'/ let oldStaticPath = mainScss.match(staticReg)[1] let oldCommonStaticPath = mainScss.match(commonStaticReg)[1] let canReWrite = false if (oldStaticPath !== staticPath) { mainScss = mainScss.replace(staticReg, function () { return '$staticPath: \''+ staticPath +'\'' }) canReWrite = true } if (oldCommonStaticPath !== commonStaticPath) { mainScss = mainScss.replace(commonStaticReg, function () { return '$commonStaticPath: \''+ commonStaticPath +'\'' }) canReWrite = true } if (canReWrite) { fs.writeFileSync(mainScssFile, mainScss) } } // 拷贝对象 // 这里实现了深、浅拷贝 const copyObject = function () { let i = 1, target = arguments[0] || {}, deep = false, length = arguments.length, name, options, src, copy, copyIsArray, clone; // 如果第一个参数的数据类型是Boolean类型 // target往后取第二个参数 if (typeof target === 'boolean') { deep = target; // 使用||运算符,排除隐式强制类型转换为false的数据类型 // 如'', 0, undefined, null, false等 // 如果target为以上的值,则设置target = {} target = arguments[1] || {}; i++; } // 如果target不是一个对象或数组或函数 if (typeof target !== 'object' && !(typeof target === 'function')) { target = {}; } // 如果arguments.length === 1 或 // typeof arguments[0] === 'boolean', // 且存在arguments[1],则直接返回target对象 if (i === length) { return target; } // 循环每个源对象 for (; i < length; i++) { // 如果传入的源对象是null或undefined // 则循环下一个源对象 if (typeof (options = arguments[i]) != null) { // 遍历所有[[emuerable]] === true的源对象 // 包括Object, Array, String // 如果遇到源对象的数据类型为Boolean, Number // for in循环会被跳过,不执行for in循环 for (name in options) { // src用于判断target对象是否存在name属性 src = target[name]; // copy用于复制 copy = options[name]; // 判断copy是否是数组 copyIsArray = Array.isArray(copy); if (deep && copy && (typeof copy === 'object' || copyIsArray)) { if (copyIsArray) { copyIsArray = false; // 如果目标对象存在name属性且是一个数组 // 则使用目标对象的name属性,否则重新创建一个数组,用于复制 clone = src && Array.isArray(src) ? src : []; } else { // 如果目标对象存在name属性且是一个对象 // 则使用目标对象的name属性,否则重新创建一个对象,用于复制 clone = src && typeof src === 'object' ? src : {}; } // 深复制,所以递归调用copyObject函数 // 返回值为target对象,即clone对象 // copy是一个源对象 target[name] = copyObject(deep, clone, copy); } else if (copy !== undefined){ // 浅复制,直接复制到target对象上 target[name] = copy; } } } } // 返回目标对象 return target; } exports.copyObject = copyObject