From 27afea864911a3adef4e030eb7126e8132d310c2 Mon Sep 17 00:00:00 2001 From: yutent Date: Thu, 18 May 2023 12:04:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BD=BF=E7=94=A8=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=E7=9A=84=E6=A0=B7=E5=BC=8F=E6=96=87=E4=BB=B6=E6=97=B6?= =?UTF-8?q?=E7=83=AD=E6=9B=B4=E6=96=B0=E5=A4=B1=E6=95=88=E7=9A=84bug;=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0legacy=E6=A8=A1=E5=BC=8F=E7=9A=84=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/compile-vue.js | 246 ++++++++++++++++++++++++--------------------- lib/constants.js | 92 ++++++++++------- lib/dev.js | 15 ++- lib/prod.js | 7 +- package.json | 2 +- 5 files changed, 202 insertions(+), 160 deletions(-) diff --git a/lib/compile-vue.js b/lib/compile-vue.js index fe2742a..833bee3 100644 --- a/lib/compile-vue.js +++ b/lib/compile-vue.js @@ -21,9 +21,10 @@ import { STYLE_EXP, HTML_EXP, CSS_SHEET_EXP, - HMR_SCRIPT, V_DEEP, - PERCENT_EXP + PERCENT_EXP, + SHEETS_DEF, + createHmrScript } from './constants.js' const OPTIONS = { @@ -126,7 +127,7 @@ export function parseJs( { IS_MPA, currentPage, IS_ENTRY, DEPLOY_PATH, LEGACY_MODE } = {}, filename ) { - let fixedStyle = '\n\n' + let fixedStyle = '' let ASSETS_DIR = '/@/' let isBuild = process.env.NODE_ENV === 'production' @@ -134,10 +135,6 @@ export function parseJs( ASSETS_DIR = '/assets/' } - if (IS_ENTRY) { - fixedStyle += 'const __sheets__ = [...document.adoptedStyleSheets];\n' - } - try { code = Es.transformSync(code).code || '' } catch (e) { @@ -156,115 +153,121 @@ export function parseJs( ) } - return ( - code - .replace(/\r\n/g, '\n') - .replace(/process\.env\.NODE_ENV/g, `'${process.env.NODE_ENV}'`) - .replace( - /import ([\w\W]*?) from (["'])(.*?)\2/g, - function (m, alias, q, name) { - if (name.startsWith('@/')) { - name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) - } - - if (!imports[name]) { - if (name.startsWith('./') || name.startsWith('../')) { - if (IS_ENTRY) { - if (IS_MPA) { - name = `pages/${currentPage}/` + name - } - name = urlJoin(DEPLOY_PATH, ASSETS_DIR, name) - } - } else if ( - name.startsWith('/') && - !name.startsWith('//') && - !name.startsWith(urlJoin(DEPLOY_PATH, ASSETS_DIR)) - ) { - name = name.replace(/^\//, urlJoin(DEPLOY_PATH, ASSETS_DIR)) - } - - if (!name.endsWith('.js') && !name.endsWith('.vue')) { - if (name.includes('components')) { - name += '.vue' - } else { - name += '.js' - } - } - } - 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') - } + code = code + .replace(/\r\n/g, '\n') + .replace(/process\.env\.NODE_ENV/g, `'${process.env.NODE_ENV}'`) + .replace( + /import ([\w\W]*?) from (["'])(.*?)\2/g, + function (m, alias, q, name) { if (name.startsWith('@/')) { name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) } - return `import('${name}')` - }) - .replace(/import (["'])(.*?)\1/g, function (m, q, name) { - if (name.endsWith('.css') || name.endsWith('.scss')) { - if (name.startsWith('@/')) { - name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) - } - if (isBuild) { - name = name.replace(/\.scss/, '.css') - } - // 修正那反人类的windows路径 - let _name = name.replace(/\\/g, '/') - let tmp = `style_${uuid()}` - - if (LEGACY_MODE) { - fixedStyle += `${tmp}.then(r => { - let stylesheet = new CSSStyleSheet() - stylesheet.path = '${_name}' - stylesheet.replaceSync(r) - __sheets__.push(stylesheet) -}) -` - return `${tmp} = window.fetch('${name}').then(r => r.text())` - } else { - fixedStyle += `${tmp}.path = '${_name}'\n__sheets__.push(${tmp})\n` - - return `import ${tmp} from '${name}' assert { type: 'css' }` - } - } else { - if (name.startsWith('@/')) { - name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) - } - // - if (!imports[name]) { - if (name.startsWith('./') || name.startsWith('../')) { - if (IS_ENTRY) { - if (IS_MPA) { - name = `${currentPage}/` + name - } - name = urlJoin(DEPLOY_PATH, ASSETS_DIR, name) + if (!imports[name]) { + if (name.startsWith('./') || name.startsWith('../')) { + if (IS_ENTRY) { + if (IS_MPA) { + name = `pages/${currentPage}/` + name } - } else if ( - name.startsWith('/') && - !name.startsWith('//') && - !name.startsWith(urlJoin(DEPLOY_PATH, ASSETS_DIR)) - ) { - name = name.replace(/^\//, urlJoin(DEPLOY_PATH, ASSETS_DIR)) + name = urlJoin(DEPLOY_PATH, ASSETS_DIR, name) } + } else if ( + name.startsWith('/') && + !name.startsWith('//') && + !name.startsWith(urlJoin(DEPLOY_PATH, ASSETS_DIR)) + ) { + name = name.replace(/^\//, urlJoin(DEPLOY_PATH, ASSETS_DIR)) + } - if (!name.endsWith('.js') && !name.endsWith('.vue')) { + if (!name.endsWith('.js') && !name.endsWith('.vue')) { + if (name.includes('components')) { + name += '.vue' + } else { name += '.js' } } - - return `import '${name}'` } - }) + - fixedStyle + - (IS_ENTRY ? '\ndocument.adoptedStyleSheets = __sheets__' : '') - ) + 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') + } + if (name.startsWith('@/')) { + name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) + } + return `import('${name}')` + }) + .replace(/import (["'])(.*?)\1/g, function (m, q, name) { + if (name.endsWith('.css') || name.endsWith('.scss')) { + if (name.startsWith('@/')) { + name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) + } + + if (isBuild) { + name = name.replace(/\.scss/, '.css') + } + // 修正那反人类的windows路径 + let _name = name.replace(/\\/g, '/').replace('@/', '') + let tmp = `style_${uuid()}` + + if (LEGACY_MODE) { + fixedStyle += `${tmp}.then(r => { + let stylesheet = document.createElement('style') + stylesheet.setAttribute('name', '${_name}') + stylesheet.textContent = r + document.head.appendChild(stylesheet) +}) +` + return `const ${tmp} = window.fetch('${name}').then(r => r.text())` + } else { + fixedStyle += `${tmp}.path = '${_name}'\n__sheets__.push(${tmp})\n` + + return `import ${tmp} from '${name}' assert { type: 'css' }` + } + } else { + if (name.startsWith('@/')) { + name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) + } + // + if (!imports[name]) { + if (name.startsWith('./') || name.startsWith('../')) { + if (IS_ENTRY) { + if (IS_MPA) { + name = `${currentPage}/` + name + } + name = urlJoin(DEPLOY_PATH, ASSETS_DIR, name) + } + } else if ( + name.startsWith('/') && + !name.startsWith('//') && + !name.startsWith(urlJoin(DEPLOY_PATH, ASSETS_DIR)) + ) { + name = name.replace(/^\//, urlJoin(DEPLOY_PATH, ASSETS_DIR)) + } + + if (!name.endsWith('.js') && !name.endsWith('.vue')) { + name += '.js' + } + } + + return `import '${name}'` + } + }) + + if (fixedStyle) { + code += '\n\n' + (LEGACY_MODE ? '' : SHEETS_DEF) + fixedStyle + + if (IS_ENTRY && !LEGACY_MODE) { + code += '\ndocument.adoptedStyleSheets = __sheets__' + } + } + + return code } /** @@ -273,6 +276,7 @@ export function parseJs( * @return 返回转换后的js代码 */ export function compileVue(file, imports, options = {}) { + // 修正那反人类的windows路径 let filename = file.slice(options.SOURCE_DIR.length).replace(/\\/g, '/') let code = (fs.cat(file) || '').toString().replace(/\r\n/g, '\n') let CACHE = options.CACHE || {} @@ -360,22 +364,34 @@ function render(_ctx, _cache) { output += parseJs(js, imports, options, file).replace( 'export default {', - `\nconst __sheets__ = [...document.adoptedStyleSheets]\n${html}\n\nconst __sfc__ = {\n render,\n` + `\n${ + options.LEGACY_MODE ? '' : SHEETS_DEF + }${html}\n\nconst __sfc__ = {\n render,\n` ) if (scss) { CACHE[file].css = scss - // 修正那反人类的windows路径 - output += ` + if (options.LEGACY_MODE) { + output += ` { - let stylesheet = new CSSStyleSheet() - stylesheet.path = '${filename}' - stylesheet.replaceSync(\`${scss}\`) - __sheets__.push(stylesheet) + let stylesheet = document.createElement('style') + stylesheet.setAttribute('name', '${filename}') + stylesheet.textContent = \`${scss}\` + document.head.appendChild(stylesheet) } -document.adoptedStyleSheets = __sheets__ ` + } else { + output += ` + { + let stylesheet = new CSSStyleSheet() + stylesheet.path = '${filename}' + stylesheet.replaceSync(\`${scss}\`) + __sheets__.push(stylesheet) + } + document.adoptedStyleSheets = __sheets__ +` + } } if (scoped) { output += `__sfc__.__scopeId = '${scopeId}'\n` @@ -388,14 +404,14 @@ document.adoptedStyleSheets = __sheets__ /** * 解析模板html */ -export function parseHtml(html, { page, imports, entry }) { +export function parseHtml(html, { page, imports, entry, LEGACY_MODE }) { return html .replace(/\r\n/g, '\n') .replace( '', `${ process.env.NODE_ENV === 'development' - ? ` \n` : '' diff --git a/lib/constants.js b/lib/constants.js index f7ef16d..a236644 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -16,47 +16,63 @@ export const COMMON_HEADERS = { 'Cache-Control': 'no-store' } -export const HMR_SCRIPT = ` -!(function vue_live_hmr(){ - var ws = new WebSocket(\`ws\${location.protocol === 'https:' ? 's' : ''}://\${location.host}/ws-vue-live\`) +export const SHEETS_DEF = + 'const __sheets__ = [...document.adoptedStyleSheets];\n' - ws.addEventListener('open', function (r) { - if(vue_live_hmr.closed){ - delete vue_live_hmr.closed - location.reload() - } - console.log('vue-live hmr ready...') - }) - - ws.addEventListener('close', function(){ - vue_live_hmr.closed = true - setTimeout(vue_live_hmr, 2000) - }) +export function createHmrScript(legacy) { + return ` + !(function vue_live_hmr(){ + var ws = new WebSocket(\`ws\${location.protocol === 'https:' ? 's' : ''}://\${location.host}/ws-vue-live\`) - ws.addEventListener('message', function (ev) { - var { action, data } = JSON.parse(ev.data) - - switch (action) { - case 'reload': + ws.addEventListener('open', function (r) { + if(vue_live_hmr.closed){ + delete vue_live_hmr.closed location.reload() - break + } + console.log('vue-live hmr ready...') + }) - case 'render': - { - let tmp = [...document.adoptedStyleSheets] - for (let i = -1, it; (it = tmp[++i]); ) { - if (it.path === data.path) { - let stylesheet = new CSSStyleSheet() - stylesheet.path = data.path - stylesheet.replaceSync(data.content) - tmp[i] = stylesheet - document.adoptedStyleSheets = tmp - break + ws.addEventListener('close', function(){ + vue_live_hmr.closed = true + setTimeout(vue_live_hmr, 2000) + }) + + ws.addEventListener('message', function (ev) { + var { action, data } = JSON.parse(ev.data) + + switch (action) { + case 'reload': + location.reload() + break + + case 'render': + { + ${ + legacy + ? ` + let stylesheet = document.head.children.namedItem(data.path) + if (stylesheet) { + stylesheet.textContent = data.content + } + ` + : ` + let tmp = [...document.adoptedStyleSheets] + for (let i = -1, it; (it = tmp[++i]); ) { + if (it.path === data.path) { + let stylesheet = new CSSStyleSheet() + stylesheet.path = data.path + stylesheet.replaceSync(data.content) + tmp[i] = stylesheet + document.adoptedStyleSheets = tmp + break + } + } + ` } } - } - break - } - }) -})() -` + break + } + }) + })() + ` +} diff --git a/lib/dev.js b/lib/dev.js index 32bdc6f..7f0e404 100644 --- a/lib/dev.js +++ b/lib/dev.js @@ -164,14 +164,19 @@ export default async function createServer(root = '', conf = {}) { LEGACY_MODE }) - code = parseHtml(html, { page, imports: conf.imports, entry }) + code = parseHtml(html, { + page, + imports: conf.imports, + entry, + LEGACY_MODE + }) } break case 'vue': { - let rpath = pathname.replace(/@\//, '') + let rpath = pathname.replace('@/', '') let file if (IS_MPA) { @@ -208,9 +213,9 @@ export default async function createServer(root = '', conf = {}) { case 'scss': case 'css': { - let file = join(SOURCE_DIR, pathname.replace(/@\//, '')) + let file = join(SOURCE_DIR, pathname.replace('@/', '')) if (!fs.isfile(file)) { - file = join(PUBLIC_DIR, pathname.replace(/@\//, '')) + file = join(PUBLIC_DIR, pathname.replace('@/', '')) if (!fs.isfile(file)) { friendlyErrors(pathname, ext) @@ -232,7 +237,7 @@ export default async function createServer(root = '', conf = {}) { case 'js': { - let rpath = pathname.replace(/@\//, '') + let rpath = pathname.replace('@/', '') let file if (IS_MPA) { diff --git a/lib/prod.js b/lib/prod.js index 1f13aed..a47e3e6 100644 --- a/lib/prod.js +++ b/lib/prod.js @@ -60,7 +60,12 @@ export default function compile(root = '', dist = '', conf = {}) { entry = parseJs(entry, conf.imports, { ...options, IS_ENTRY: true }) - let code = parseHtml(template, { page, imports: conf.imports, entry }) + let code = parseHtml(template, { + page, + imports: conf.imports, + entry, + LEGACY_MODE + }) fs.echo(code, join(dist, `${currentPage}.html`)) continue diff --git a/package.json b/package.json index 74762af..a6acd26 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "fite", "type": "module", - "version": "1.0.3", + "version": "1.1.0", "bin": { "fite": "index.js" },