From 47668b541989c4abd48a4b232654b4e33c795714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Thu, 24 Mar 2022 22:51:30 +0900 Subject: [PATCH] fix: inline style css sourcemap (#7434) --- .../css-sourcemap/__tests__/serve.spec.ts | 66 +++++++++++++++++++ packages/playground/css-sourcemap/index.html | 8 +++ packages/vite/src/node/plugins/html.ts | 31 ++++----- .../src/node/server/middlewares/indexHtml.ts | 23 ++++--- .../vite/src/node/server/pluginContainer.ts | 2 +- 5 files changed, 103 insertions(+), 27 deletions(-) diff --git a/packages/playground/css-sourcemap/__tests__/serve.spec.ts b/packages/playground/css-sourcemap/__tests__/serve.spec.ts index 50c256298143ab..fb2dd97967d91f 100644 --- a/packages/playground/css-sourcemap/__tests__/serve.spec.ts +++ b/packages/playground/css-sourcemap/__tests__/serve.spec.ts @@ -30,6 +30,66 @@ if (!isBuild) { return m } + test('inline css', async () => { + const css = await getStyleTagContentIncluding('.inline ') + const map = extractSourcemap(css) + expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(` + Object { + "mappings": "AAGO;AACP,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACX,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACf,CAAC,CAAC,CAAC;", + "sources": Array [ + "/root/index.html", + ], + "sourcesContent": Array [ + " + + + + +
+

CSS Sourcemap

+ +

<inline>

+ +

<linked>: no import

+

<linked>: with import

+ +

<imported>: no import

+

<imported>: with import

+ +

<imported sass>

+

<imported sass> with module

+ +

<imported less> with string additionalData

+ +

<imported stylus>

+
+ + + ", + ], + "version": 3, + } + `) + }) + test('linked css', async () => { const res = await page.request.get( new URL('./linked.css', page.url()).href, @@ -207,6 +267,12 @@ if (!isBuild) { } `) }) + + test('should not output missing source file warning', () => { + serverLogs.forEach((log) => { + expect(log).not.toMatch(/Sourcemap for .+ points to missing source files/) + }) + }) } else { test('this file only includes test for serve', () => { expect(true).toBe(true) diff --git a/packages/playground/css-sourcemap/index.html b/packages/playground/css-sourcemap/index.html index 2fedceb8f2be44..d0e9980b926125 100644 --- a/packages/playground/css-sourcemap/index.html +++ b/packages/playground/css-sourcemap/index.html @@ -1,9 +1,17 @@ + +

CSS Sourcemap

+

<inline>

+

<linked>: no import

<linked>: with import

diff --git a/packages/vite/src/node/plugins/html.ts b/packages/vite/src/node/plugins/html.ts index c8a5617a92b253..733b2e4829f12c 100644 --- a/packages/vite/src/node/plugins/html.ts +++ b/packages/vite/src/node/plugins/html.ts @@ -5,7 +5,8 @@ import type { OutputAsset, OutputBundle, OutputChunk, - RollupError + RollupError, + SourceMapInput } from 'rollup' import { cleanUrl, @@ -54,7 +55,7 @@ export const isHTMLRequest = (request: string): boolean => // HTML Proxy Caches are stored by config -> filePath -> index export const htmlProxyMap = new WeakMap< ResolvedConfig, - Map> + Map> >() // HTML Proxy Transform result are stored by config @@ -83,7 +84,7 @@ export function htmlInlineProxyPlugin(config: ResolvedConfig): Plugin { const file = cleanUrl(id) const url = file.replace(normalizePath(config.root), '') const result = htmlProxyMap.get(config)!.get(url)![index] - if (typeof result === 'string') { + if (result) { return result } else { throw new Error(`No matching HTML proxy module found from ${id}`) @@ -97,7 +98,7 @@ export function addToHTMLProxyCache( config: ResolvedConfig, filePath: string, index: number, - code: string + result: { code: string; map?: SourceMapInput } ): void { if (!htmlProxyMap.get(config)) { htmlProxyMap.set(config, new Map()) @@ -105,7 +106,7 @@ export function addToHTMLProxyCache( if (!htmlProxyMap.get(config)!.get(filePath)) { htmlProxyMap.get(config)!.set(filePath, []) } - htmlProxyMap.get(config)!.get(filePath)![index] = code + htmlProxyMap.get(config)!.get(filePath)![index] = result } export function addToHTMLProxyTransformResult( @@ -284,12 +285,9 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { .join('') // const filePath = id.replace(normalizePath(config.root), '') - addToHTMLProxyCache( - config, - filePath, - inlineModuleIndex, - contents - ) + addToHTMLProxyCache(config, filePath, inlineModuleIndex, { + code: contents + }) js += `\nimport "${id}?html-proxy&index=${inlineModuleIndex}.js"` shouldRemove = true } @@ -364,7 +362,7 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { const styleNode = inlineStyle.value! const code = styleNode.content! const filePath = id.replace(normalizePath(config.root), '') - addToHTMLProxyCache(config, filePath, inlineModuleIndex, code) + addToHTMLProxyCache(config, filePath, inlineModuleIndex, { code }) // will transform with css plugin and cache result with css-post plugin js += `\nimport "${id}?html-proxy&inline-css&index=${inlineModuleIndex}.css"` @@ -382,12 +380,9 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin { const styleNode = node.children.pop() as TextNode const filePath = id.replace(normalizePath(config.root), '') inlineModuleIndex++ - addToHTMLProxyCache( - config, - filePath, - inlineModuleIndex, - styleNode.content - ) + addToHTMLProxyCache(config, filePath, inlineModuleIndex, { + code: styleNode.content + }) js += `\nimport "${id}?html-proxy&index=${inlineModuleIndex}.css"` shouldRemove = true } diff --git a/packages/vite/src/node/server/middlewares/indexHtml.ts b/packages/vite/src/node/server/middlewares/indexHtml.ts index 07b2693c07f995..ca2538bd9507ed 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, ElementNode } from '@vue/compiler-dom' +import type { AttributeNode, ElementNode, TextNode } from '@vue/compiler-dom' import { NodeTypes } from '@vue/compiler-dom' import type { Connect } from 'types/connect' import type { IndexHtmlTransformHook } from '../../plugins/html' @@ -38,7 +38,9 @@ function getHtmlFilename(url: string, server: ViteDevServer) { if (url.startsWith(FS_PREFIX)) { return decodeURIComponent(fsPathFromId(url)) } else { - return decodeURIComponent(path.join(server.config.root, url.slice(1))) + return decodeURIComponent( + normalizePath(path.join(server.config.root, url.slice(1))) + ) } } @@ -90,7 +92,7 @@ const processNodeUrl = ( } const devHtmlHook: IndexHtmlTransformHook = async ( html, - { path: htmlPath, server, originalUrl } + { path: htmlPath, filename, server, originalUrl } ) => { const { config, moduleGraph } = server! const base = config.base || '/' @@ -104,12 +106,17 @@ const devHtmlHook: IndexHtmlTransformHook = async ( const url = filePath.replace(normalizePath(config.root), '') - const contents = node.children - .map((child: any) => child.content || '') - .join('') + const contentNode = node.children[0] as TextNode + + const code = contentNode.content + const map = new MagicString(html) + .snip(contentNode.loc.start.offset, contentNode.loc.end.offset) + .generateMap({ hires: true }) + map.sources = [filename] + map.file = filename // add HTML Proxy to Map - addToHTMLProxyCache(config, url, inlineModuleIndex, contents) + addToHTMLProxyCache(config, url, inlineModuleIndex, { code, map }) // inline js module. convert to src="proxy" const modulePath = `${ @@ -141,7 +148,7 @@ const devHtmlHook: IndexHtmlTransformHook = async ( if (src) { processNodeUrl(src, s, config, htmlPath, originalUrl, moduleGraph) - } else if (isModule) { + } else if (isModule && node.children.length) { addInlineModule(node, 'js') } } diff --git a/packages/vite/src/node/server/pluginContainer.ts b/packages/vite/src/node/server/pluginContainer.ts index 590648ed58d164..5efc2670c0f81a 100644 --- a/packages/vite/src/node/server/pluginContainer.ts +++ b/packages/vite/src/node/server/pluginContainer.ts @@ -442,7 +442,7 @@ export async function createPluginContainer( ? new MagicString(this.originalCode).generateMap({ includeContent: true, hires: true, - source: this.filename + source: cleanUrl(this.filename) }) : null }