esm增加对json文件的支持;优化legacy模式

master 1.3.0
yutent 2024-03-01 18:39:39 +08:00
parent 100c372718
commit a15bd9ea95
6 changed files with 84 additions and 23 deletions

View File

@ -18,7 +18,8 @@ import {
CSS_SHEET_EXP, CSS_SHEET_EXP,
V_DEEP, V_DEEP,
PERCENT_EXP, PERCENT_EXP,
SHEETS_DEF SHEETS_DEF,
LEGACY_POLYFILL
} from './constants.js' } from './constants.js'
import { createHmrScript, md5, uuid, urlJoin } from './utils.js' import { createHmrScript, md5, uuid, urlJoin } from './utils.js'
@ -26,6 +27,10 @@ const OPTIONS = {
style: 'compressed' style: 'compressed'
} }
function minify(code) {
return Es.transformSync(code, { minify: true }).code.trim()
}
// 处理css中的 :deep() // 处理css中的 :deep()
function parseVDeep(curr, val, scoped) { function parseVDeep(curr, val, scoped) {
let res = V_DEEP.exec(curr) let res = V_DEEP.exec(curr)
@ -149,11 +154,12 @@ export function parseJs(
.replace(/\r\n/g, '\n') .replace(/\r\n/g, '\n')
.replace(/process\.env\.NODE_ENV/g, `'${process.env.NODE_ENV}'`) .replace(/process\.env\.NODE_ENV/g, `'${process.env.NODE_ENV}'`)
.replace( .replace(
/(import|export) ([\w\W]*?) from (["'])(.*?)\3/g, /(import|export) ([^'"]*?) from (["'])(.*?)\3/g,
function (m, t, alias, q, name) { function (m, t, alias, q, name) {
if (name.startsWith('@/')) { if (name.startsWith('@/')) {
name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR)) name = name.replace('@/', urlJoin(DEPLOY_PATH, ASSETS_DIR))
} }
let isJson = name.endsWith('.json')
if (!imports[name]) { if (!imports[name]) {
if (name.startsWith('./') || name.startsWith('../')) { if (name.startsWith('./') || name.startsWith('../')) {
@ -173,6 +179,7 @@ export function parseJs(
if ( if (
!name.endsWith('.js') && !name.endsWith('.js') &&
!isJson &&
!name.endsWith('.mjs') && !name.endsWith('.mjs') &&
!name.endsWith('.vue') !name.endsWith('.vue')
) { ) {
@ -190,13 +197,20 @@ export function parseJs(
return `${t} ${alias} from '${name}'` return `${t} ${alias} from '${name}'`
} }
let _alias = alias let _alias = alias
let _import = ''
if (alias.includes('* as')) { if (alias.includes('* as')) {
_alias = ' default ' + alias.replace('* as', '').trim() _alias = ' default ' + alias.replace('* as', '').trim()
} }
return `import ${alias} from '${name}'${ if (LEGACY_MODE && isJson) {
t === 'export' ? `\nexport ${_alias}` : '' _import = `const ${alias} = await __fite_import('${name}', import.meta.url)`
}` } else {
_import = `import ${alias} from '${name}'${
isJson ? ' assert { type: "json" }' : ''
}`
}
_import += t === 'export' ? `\nexport ${_alias}` : ''
return _import
} }
) )
.replace(/import\((['"])(.*?)\1\)/g, function (m, q, name) { .replace(/import\((['"])(.*?)\1\)/g, function (m, q, name) {
@ -229,7 +243,7 @@ export function parseJs(
document.head.appendChild(stylesheet) document.head.appendChild(stylesheet)
}) })
` `
return `const ${tmp} = window.fetch('${name}').then(r => r.text())` return `const ${tmp} = __fite_import('${name}', import.meta.url)`
} else { } else {
fixedStyle += `${tmp}.path = '${_name}'\n__sheets__.push(${tmp})\n` fixedStyle += `${tmp}.path = '${_name}'\n__sheets__.push(${tmp})\n`
@ -258,6 +272,7 @@ export function parseJs(
if ( if (
!name.endsWith('.js') && !name.endsWith('.js') &&
!name.endsWith('.json') &&
!name.endsWith('.mjs') && !name.endsWith('.mjs') &&
!name.endsWith('.vue') !name.endsWith('.vue')
) { ) {
@ -423,9 +438,9 @@ export function parseHtml(html, { page, imports, entry, LEGACY_MODE }) {
'</head>', '</head>',
`${ `${
process.env.NODE_ENV === 'development' process.env.NODE_ENV === 'development'
? ` <script>${Es.transformSync(createHmrScript(LEGACY_MODE), { ? ` <script>${minify(createHmrScript(LEGACY_MODE))}</script>\n`
minify: true : LEGACY_MODE
}).code.trim()}</script>\n` ? ` <script>${minify(LEGACY_POLYFILL)}</script>\n`
: '' : ''
}</head>` }</head>`
) )

View File

@ -67,6 +67,16 @@ export async function compileFiles(
} }
break break
case '.json':
{
let code = fs.cat(path)
code = JSON.stringify(JSON.parse(code + ''))
fs.echo(code, join(dist, 'assets/', pageDir, it.name))
}
break
case '.scss': case '.scss':
case '.css': case '.css':
{ {

View File

@ -18,3 +18,34 @@ export const COMMON_HEADERS = {
export const SHEETS_DEF = export const SHEETS_DEF =
'const __sheets__ = [...document.adoptedStyleSheets];\n' 'const __sheets__ = [...document.adoptedStyleSheets];\n'
export const LEGACY_POLYFILL = `!(function(){
function join(p1, p2) {
let tmp1 = p1.split('/')
let tmp2 = p2.split('/')
if (tmp1.at(-1) === '') {
tmp1.pop()
}
while (tmp2.length) {
let tmp = tmp2.shift()
if (tmp === '.' || tmp === '') {
continue
} else if (tmp === '..') {
tmp1.pop()
} else {
tmp1.push(tmp)
}
}
return tmp1.join('/')
}
window.__fite_import = function(url,relPath){
let isJson = url.endsWith('.json')
let absPath = relPath.split('/').slice(0, -1).join('/')
let req
if(url.startsWith('./') || url.startsWith('../')) {
url = join(absPath, url)
}
return window.fetch(url).then(r => isJson ? r.json() : r.text())
}
})()`

View File

@ -255,6 +255,7 @@ export default async function createServer(root = '', conf = {}) {
} }
break break
case 'json':
case 'js': case 'js':
{ {
let rpath = pathname.replace('@/', '') let rpath = pathname.replace('@/', '')
@ -282,18 +283,20 @@ export default async function createServer(root = '', conf = {}) {
res.end('') res.end('')
return return
} }
code = parseJs( if (ext === 'js') {
code + '', code = parseJs(
conf.imports, code + '',
{ conf.imports,
IS_MPA, {
currentPage, IS_MPA,
DEPLOY_PATH, currentPage,
LEGACY_MODE DEPLOY_PATH,
}, LEGACY_MODE
file },
) file
res.setHeader('content-type', MIME_TYPES.js) )
}
res.setHeader('content-type', MIME_TYPES[ext])
} }
break break

View File

@ -8,6 +8,7 @@ import { createHash, randomUUID } from 'node:crypto'
import { join } from 'node:path' import { join } from 'node:path'
import { gzipSync } from 'node:zlib' import { gzipSync } from 'node:zlib'
import { red, cyan, blue } from 'kolorist' import { red, cyan, blue } from 'kolorist'
import { LEGACY_POLYFILL } from './constants.js'
// 修正路径合并 避免在windows下被转义 // 修正路径合并 避免在windows下被转义
export function urlJoin(...args) { export function urlJoin(...args) {
@ -39,7 +40,7 @@ export function friendlyErrors(pathname, ext = '') {
export function createHmrScript(legacy, session = '') { export function createHmrScript(legacy, session = '') {
return ` return `
!(function vue_live_hmr(){ !(function vue_live_hmr(){
var ws = new WebSocket(\`ws\${location.protocol === 'https:' ? 's' : ''}://\${location.host}/ws-fite-hmr?session=\${btoa(location.pathname).replace(/[=\+\/]/g, '')}&lock=\${localStorage.getItem(location.pathname) || 0}\`) let ws = new WebSocket(\`ws\${location.protocol === 'https:' ? 's' : ''}://\${location.host}/ws-fite-hmr?session=\${btoa(location.pathname).replace(/[=\+\/]/g, '')}&lock=\${localStorage.getItem(location.pathname) || 0}\`)
ws.addEventListener('open', function (r) { ws.addEventListener('open', function (r) {
if(vue_live_hmr.closed){ if(vue_live_hmr.closed){
@ -93,6 +94,7 @@ export function createHmrScript(legacy, session = '') {
break break
} }
}) })
${LEGACY_POLYFILL}
})() })()
` `
} }

View File

@ -1,7 +1,7 @@
{ {
"name": "fite", "name": "fite",
"type": "module", "type": "module",
"version": "1.2.0", "version": "1.3.0",
"bin": { "bin": {
"fite": "index.js" "fite": "index.js"
}, },