From 69029895f1f18b74230c6443bec7ac24d232cadf Mon Sep 17 00:00:00 2001 From: yutent Date: Tue, 11 Oct 2022 19:31:04 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=94=9F=E4=BA=A7=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.js | 14 +++++--- lib/compile-vue.js | 37 +++++++++++++++++----- lib/dev.js | 79 +++++----------------------------------------- lib/prod.js | 77 ++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 +- 5 files changed, 123 insertions(+), 86 deletions(-) diff --git a/index.js b/index.js index 89220aa..7ef3552 100755 --- a/index.js +++ b/index.js @@ -6,12 +6,13 @@ * @date 2022/09/28 15:12:45 */ +import fs from 'iofs' import { join } from 'path' import createServer from './lib/dev.js' import compile from './lib/prod.js' -const WORK_SPACE = process.env.INIT_CWD +const WORK_SPACE = process.env.PWD const CONFIG_FILE = join(WORK_SPACE, 'vue.live.js') const SOURCE_DIR = join(WORK_SPACE, 'src') @@ -25,17 +26,22 @@ switch (args[0]) { createServer(SOURCE_DIR, conf.default) }) .catch(err => { - console.log('Import Error:', err) + console.log(err) }) break case 'build': import(CONFIG_FILE) .then(function (conf) { - compile(SOURCE_DIR, conf.default) + let dist = conf.buildDir || 'dist' + if (fs.isdir(dist)) { + fs.rm(dist, true) + } + fs.mkdir(dist) + compile(SOURCE_DIR, dist, conf.default) }) .catch(err => { - console.log('Import Error:', err) + console.log(err) }) break } diff --git a/lib/compile-vue.js b/lib/compile-vue.js index a1ea876..2664939 100644 --- a/lib/compile-vue.js +++ b/lib/compile-vue.js @@ -14,8 +14,6 @@ const OPTIONS = { indentWidth: 2 } -let imports = {} - /** * 编译scss为css * @param file 文件路径或scss代码 @@ -38,7 +36,7 @@ export function compileScss(file, style = 'expanded') { * 主要是处理js的依赖引用 * @param code js代码 */ -export function parseJs(code = '', { IS_MPA, currentPage, root, pagesDir } = {}) { +export function parseJs(code = '', imports, { IS_MPA, currentPage } = {}, isBuild) { let fixedStyle = '\n\n' return ( @@ -66,8 +64,17 @@ export function parseJs(code = '', { IS_MPA, currentPage, root, pagesDir } = {}) } } } + if (isBuild) { + name = name.replace(/\.vue$/, '.js') + } return `import ${alias} from '${name}'` }) + .replace(/import\((['"])(.*?)\1\)/g, function (m, q, name) { + if (isBuild) { + name = name.replace(/\.vue$/, '.js') + } + return `import('${name}')` + }) .replace(/import (["'])(.*?)\1/g, function (m, q, name) { if (name.endsWith('.css') || name.endsWith('.scss')) { if (name.startsWith('@/')) { @@ -81,7 +88,7 @@ export function parseJs(code = '', { IS_MPA, currentPage, root, pagesDir } = {}) if (name.startsWith('@/')) { name = name.replace('@/', '/assets/js/') } - // console.log(name, imports[name]) + // if (!imports[name]) { if (!name.startsWith('/') && !name.startsWith('./')) { name = '/' + name @@ -102,7 +109,7 @@ export function parseJs(code = '', { IS_MPA, currentPage, root, pagesDir } = {}) * @param file 文件路径 * @return 返回转换后的js代码 */ -export function compileVue(file, conf, options = {}) { +export function compileVue(file, imports, options = {}, isBuild) { let code = (fs.cat(file) || '').toString() let js = code.match(JS_EXP) @@ -111,14 +118,12 @@ export function compileVue(file, conf, options = {}) { let fixedStyle = '\n\n' - imports = conf.imports - // console.log(typeof scss) scss = [...scss].flatMap(it => (it ? it[1] : '')) js = js ? js[1] : '' html = (html ? html[1] : '').replace(/`/g, '\\`').replace(/\$\{/g, '\\${') - js = parseJs(js, options).replace( + js = parseJs(js, imports, options, isBuild).replace( 'export default {', `${fixedStyle}export default {\n template: \`${html}\`,` ) @@ -134,3 +139,19 @@ export function compileVue(file, conf, options = {}) { return js } + +/** + * 解析模板html + */ +export function parseHtml(html, { page, imports, entry }) { + return html + .replace( + '', + " " + ) + .replace('{{title}}', page.title || '') + .replace('{{keywords}}', page.keywords || '') + .replace('{{description}}', page.description || '') + .replace('{{importmap}}', JSON.stringify({ imports })) + .replace('', ``) +} diff --git a/lib/dev.js b/lib/dev.js index 903694e..f57468c 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -3,12 +3,11 @@ import fs from 'iofs' import { join, resolve, dirname } from 'path' import { parse } from 'url' -import { compileScss, parseJs, compileVue } from './compile-vue.js' +import { compileScss, parseJs, compileVue, parseHtml } from './compile-vue.js' import MIME_TYPES from './mime-tpyes.js' import { COMMON_HEADERS } from './constants.js' -const decode = decodeURIComponent const noc = Buffer.from('') export default function createServer(root = '', conf = {}) { @@ -73,77 +72,15 @@ export default function createServer(root = '', conf = {}) { switch (ext) { case 'html': { - let entry = fs.cat(conf.pages[pageName].entry).toString() - let fixedStyle = '\n\n' - res.setHeader('content-type', MIME_TYPES.html) - entry = entry - .replace(/import (.*?) from (["'])(.*?)\2/g, function (m, alias, q, name) { - if (name.startsWith('@/')) { - name = name.replace('@/', '/assets/js/') - } + let page = conf.pages[pageName] + let entry = fs.cat(page.entry).toString() + let html = fs.cat(join(process.env.PWD, 'index.html')).toString() - if (!conf.imports[name]) { - if (name.startsWith('./')) { - name = name.replace('./', '/assets/js/') + entry = parseJs(entry, conf.imports, { IS_MPA, currentPage }) - if (IS_MPA) { - name += `${currentPage}/` - } - } else if (name.startsWith('/') && !name.startsWith('/assets/js/')) { - name = name.replace(/^\//, '/assets/js/') - } - - if (!name.endsWith('.js') && !name.endsWith('.vue')) { - name += '.js' - } - } - return `import ${alias} from '${name}'` - }) - .replace(/import (["'])(.*?)\1/g, function (m, q, name) { - if (name.endsWith('.css') || name.endsWith('.scss')) { - if (name.startsWith('@/')) { - name = name.replace('@/', '/assets/css/') - } - let tmp = `style${Date.now()}` - fixedStyle += `document.adoptedStyleSheets.push(${tmp})\n` - - return `import ${tmp} from '${name}' assert { type: 'css' }` - } else { - if (name.startsWith('@/')) { - name = name.replace('@/', '/assets/js/') - } - // console.log(name, conf.imports[name]) - if (!conf.imports[name]) { - if (!name.startsWith('/') && !name.startsWith('./')) { - name = '/' + name - } - - if (!name.endsWith('.js') && !name.endsWith('.vue')) { - name += '.js' - } - } - return `import '${name}'` - } - }) - - entry += fixedStyle - - code = fs.cat('./index.html').toString() - code = code - .replace( - '', - "" - ) - .replace('{{title}}', conf.pages[pageName].title || '') - .replace('{{keywords}}', conf.pages[pageName].keywords || '') - .replace('{{description}}', conf.pages[pageName].description || '') - .replace('{{importmap}}', JSON.stringify({ imports: conf.imports })) - .replace( - '', - `` - ) + code = parseHtml(html, { page, imports: conf.imports, entry }) } break @@ -163,7 +100,7 @@ export default function createServer(root = '', conf = {}) { } // console.log('>>>>', file) - code = compileVue(file, conf, { IS_MPA, currentPage, root, pagesDir }) + code = compileVue(file, conf.imports, { IS_MPA, currentPage, root, pagesDir }) res.setHeader('content-type', MIME_TYPES.js) } break @@ -192,7 +129,7 @@ export default function createServer(root = '', conf = {}) { file = file.replace(/\.js$/, '/index.js') code = fs.cat(file) } - code = parseJs(code + '') + code = parseJs(code + '', conf.imports, { IS_MPA, currentPage }) res.setHeader('content-type', MIME_TYPES.js) } diff --git a/lib/prod.js b/lib/prod.js index fa54f7a..ec54cb0 100644 --- a/lib/prod.js +++ b/lib/prod.js @@ -1,5 +1,78 @@ -/* ------------------------------- */ +import fs from 'iofs' +import { join, resolve, dirname, parse } from 'path' -export default function compile(root = '', conf = {}) { +import { compileScss, parseJs, compileVue, parseHtml } from './compile-vue.js' + +const noc = Buffer.from('') + +export default function compile(root = '', dist = '', conf = {}) { // + const IS_MPA = Object.keys(conf.pages).length > 1 + + let html = fs.cat(join(process.env.PWD, 'index.html')).toString() + + let pagesDir = '', + currentPage = '' + + if (IS_MPA) { + } else { + let page + let list = fs.ls(root, true).map(it => ({ + name: it.slice(root.length + 1), + path: it, + ext: parse(it).ext + })) + + currentPage = Object.keys(conf.pages)[0] + page = conf.pages[currentPage] + + for (let it of list) { + // 入口文件, 特殊处理 + if (it.path === page.entry) { + let entry = fs.cat(page.entry).toString() + entry = parseJs(entry, conf.imports, { IS_MPA, currentPage }, true) + + let code = parseHtml(html, { page, imports: conf.imports, entry }) + + fs.echo(code, join(dist, `${currentPage}.html`)) + + continue + } + + switch (it.ext) { + case '.vue': + { + let code = compileVue( + it.path, + conf.imports, + { IS_MPA, currentPage, root, pagesDir }, + true + ) + + fs.echo(code, join(dist, `assets/js/${it.name.split('.').shift()}.js`)) + } + break + + case '.js': + { + let code = fs.cat(it.path) + + code = parseJs(code + '', conf.imports, { IS_MPA, currentPage }, true) + fs.echo(code, join(dist, `assets/js/${it.name}`)) + } + break + + case '.png': + case '.jpg': + case '.jpeg': + case '.webp': + case '.gif': + case '.svg': + case '.ico': + case '.bmp': + fs.cp(it.path, join(dist, it.name)) + break + } + } + } } diff --git a/package.json b/package.json index ae0ca27..97dab1d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@bytedo/vue-live", "type": "module", - "version": "0.0.4", + "version": "0.0.5", "bin": { "vue-live": "index.js" },