From fae120a16c29e0573efadf1df84404f31af8c8df Mon Sep 17 00:00:00 2001 From: yoho <907415276@qq.com> Date: Mon, 14 Mar 2022 12:13:51 +0800 Subject: [PATCH] fix(hmr): hmr style tag no support in html (#7262) --- .../assets/__tests__/assets.spec.ts | 17 ++++- .../src/node/server/middlewares/indexHtml.ts | 67 ++++++++++--------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts index f65e3009a7aa71..0635236bd7369e 100644 --- a/packages/playground/assets/__tests__/assets.spec.ts +++ b/packages/playground/assets/__tests__/assets.spec.ts @@ -8,7 +8,8 @@ import { readManifest, readFile, editFile, - notifyRebuildComplete + notifyRebuildComplete, + untilUpdated } from '../../testUtils' const assetMatch = isBuild @@ -37,7 +38,7 @@ describe('injected scripts', () => { test('html-proxy', async () => { const hasHtmlProxy = await page.$( - 'script[type="module"][src="/foo/index.html?html-proxy&index=0.js"]' + 'script[type="module"][src^="/foo/index.html?html-proxy"]' ) if (isBuild) { expect(hasHtmlProxy).toBeFalsy() @@ -264,3 +265,15 @@ describe('css and assets in css in build watch', () => { }) } }) + +if (!isBuild) { + test('@import in html style tag hmr', async () => { + await untilUpdated(() => getColor('.import-css'), 'rgb(0, 136, 255)') + editFile( + './css/import.css', + (code) => code.replace('#0088ff', '#00ff88'), + true + ) + await untilUpdated(() => getColor('.import-css'), 'rgb(0, 255, 136)') + }) +} diff --git a/packages/vite/src/node/server/middlewares/indexHtml.ts b/packages/vite/src/node/server/middlewares/indexHtml.ts index 2721502c408e28..3c76d94c526930 100644 --- a/packages/vite/src/node/server/middlewares/indexHtml.ts +++ b/packages/vite/src/node/server/middlewares/indexHtml.ts @@ -1,7 +1,7 @@ import fs from 'fs' import path from 'path' import MagicString from 'magic-string' -import type { AttributeNode } from '@vue/compiler-dom' +import type { AttributeNode, ElementNode } from '@vue/compiler-dom' import { NodeTypes } from '@vue/compiler-dom' import type { Connect } from 'types/connect' import type { IndexHtmlTransformHook } from '../../plugins/html' @@ -94,9 +94,39 @@ const devHtmlHook: IndexHtmlTransformHook = async ( const base = config.base || '/' const s = new MagicString(html) - let scriptModuleIndex = -1 + let inlineModuleIndex = -1 const filePath = cleanUrl(htmlPath) + const addInlineModule = (node: ElementNode, ext: 'js' | 'css') => { + inlineModuleIndex++ + + const url = filePath.replace(normalizePath(config.root), '') + + const contents = node.children + .map((child: any) => child.content || '') + .join('') + + // add HTML Proxy to Map + addToHTMLProxyCache(config, url, inlineModuleIndex, contents) + + // inline js module. convert to src="proxy" + const modulePath = `${ + config.base + htmlPath.slice(1) + }?html-proxy&index=${inlineModuleIndex}.${ext}` + + // invalidate the module so the newly cached contents will be served + const module = server?.moduleGraph.getModuleById(modulePath) + if (module) { + server?.moduleGraph.invalidateModule(module) + } + + s.overwrite( + node.loc.start.offset, + node.loc.end.offset, + `` + ) + } + await traverseHtml(html, htmlPath, (node) => { if (node.type !== NodeTypes.ELEMENT) { return @@ -105,41 +135,18 @@ const devHtmlHook: IndexHtmlTransformHook = async ( // script tags if (node.tag === 'script') { const { src, isModule } = getScriptInfo(node) - if (isModule) { - scriptModuleIndex++ - } if (src) { processNodeUrl(src, s, config, htmlPath, originalUrl, moduleGraph) } else if (isModule) { - const url = filePath.replace(normalizePath(config.root), '') - - const contents = node.children - .map((child: any) => child.content || '') - .join('') - - // add HTML Proxy to Map - addToHTMLProxyCache(config, url, scriptModuleIndex, contents) - - // inline js module. convert to src="proxy" - const modulePath = `${ - config.base + htmlPath.slice(1) - }?html-proxy&index=${scriptModuleIndex}.js` - - // invalidate the module so the newly cached contents will be served - const module = server?.moduleGraph.getModuleById(modulePath) - if (module) { - server?.moduleGraph.invalidateModule(module) - } - - s.overwrite( - node.loc.start.offset, - node.loc.end.offset, - `` - ) + addInlineModule(node, 'js') } } + if (node.tag === 'style' && node.children.length) { + addInlineModule(node, 'css') + } + // elements with [href/src] attrs const assetAttrs = assetAttrsConfig[node.tag] if (assetAttrs) {