/* eslint-disable @lwc/lwc/no-async-await */ const path = require('path') const fs = require('fs') const recursive = require('recursive-readdir') const compiler = require('vue/compiler-sfc') const { minify } = require('terser') const babel = require('@babel/core') const presetJsx = require('@vue/babel-preset-jsx') const terserOptions = { compress: { defaults: false, }, format: { comments: (obj, token) => { const comment = token.value return comment.startsWith(' webpackChunkName') }, }, } const srcDir = path.join(process.cwd(), 'src') recursive( srcDir, [ (file, stats) => { if (stats.isDirectory()) { // 忽略自动导入目录 return ( path.basename(file) === '_import-components' || path.basename(file) === 'sd-icon-library' ) } if (path.extname(file) !== '.vue' && path.extname(file) !== '.js') { // 非vue、js文件不处理 return true } // if (path.basename(file) !== 'ext-layout.vue') { // // ext-layout.vue sd-data-table.vue sd-advance-search-btn.vue code-export.js sd-collapse-layout-render.vue sd-quill-reader.vue config-common.js sd-user-item.vue sd-webflow.vue sd-child-table-render.vue // return true // } return false }, ], function(_err, files) { files.forEach((file) => { if (file.endsWith('.vue')) { processVue(file) } else { processJS(file) } }) } ) function logError(path, error) { console.log('file:', path) } async function compileAndMinifyJS(code, path) { try { const compiled = babel.transformSync(code, { configFile: false, presets: [presetJsx], }).code // 压缩 js const minifyResult = await minify(compiled, terserOptions) return '\n/* eslint-disable */\n// sd-skip-auto-import\n' + minifyResult.code } catch (error) { logError(path, error) throw error } } async function processJS(path) { const content = fs.readFileSync(path).toString() writeFile(path, await compileAndMinifyJS(content, path)) } async function processVue(path) { const content = fs.readFileSync(path).toString() const parseResult = compiler.parseComponent(content) let script = parseResult.script.content let result if (parseResult.template) { // 有模板 // functional 组件处理不了 if (parseResult.template.attrs.functional) return let render const template = parseResult.template.content render = compiler.compileTemplate({ source: template, filename: path, compilerOptions: { whitespace: 'condense' }, }).code // render这个变量可能会冲突,改掉 render = render .replace('render = function render', '_render = function _render') .replace('render._withStripped = true', '_render._withStripped = true') const beforeTemplate = content.substring(0, parseResult.template.start) const afterTemplate = content.substring(parseResult.template.end, parseResult.script.start) const afterScript = content.substring(parseResult.script.end) const isExportDefault = script.indexOf('export default {') !== -1 let defaultExportName if (isExportDefault) { script = script.replace(/}[\s;]*$/, 'render:_render,staticRenderFns,}') } else { const match = script.match(/^export default (.*?)$/m) defaultExportName = match[1] } // 加上 render if (isExportDefault) { script = script.replace(/export default ?{/, render + '\nexport default {\n') } else { script = script.replace( 'export default ' + defaultExportName, render + '\n' + defaultExportName + '.render = _render;' + defaultExportName + '.staticRenderFns = staticRenderFns;export default ' + defaultExportName ) } result = (beforeTemplate + afterTemplate).replace(/^<\/template>$/gm, '') + (await compileAndMinifyJS(script, path)) + afterScript } else { // 没有模板 const beforeScript = content.substring(0, parseResult.script.start) const afterScript = content.substring(parseResult.script.end) result = beforeScript + (await compileAndMinifyJS(script, path)) + afterScript } writeFile(path, result) } function writeFile(jsFile, jsContent) { // 生成最终的js文件 fs.writeFile(jsFile, jsContent, (error) => { if (error) { // eslint-disable-next-line no-console console.error('Error while creating ' + jsFile) throw error } }) }