Skip to content

Commit

Permalink
fix: inline style css sourcemap (#7434)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Mar 24, 2022
1 parent fe4c1ed commit 47668b5
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 27 deletions.
66 changes: 66 additions & 0 deletions packages/playground/css-sourcemap/__tests__/serve.spec.ts
Expand Up @@ -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 [
"<link rel=\\"stylesheet\\" href=\\"./linked.css\\" />
<link rel=\\"stylesheet\\" href=\\"./linked-with-import.css\\" />
<style>
.inline {
color: red;
}
</style>
<div class=\\"wrapper\\">
<h1>CSS Sourcemap</h1>
<p class=\\"inline\\">&lt;inline&gt;</p>
<p class=\\"linked\\">&lt;linked&gt;: no import</p>
<p class=\\"linked-with-import\\">&lt;linked&gt;: with import</p>
<p class=\\"imported\\">&lt;imported&gt;: no import</p>
<p class=\\"imported-with-import\\">&lt;imported&gt;: with import</p>
<p class=\\"imported-sass\\">&lt;imported sass&gt;</p>
<p class=\\"imported-sass-module\\">&lt;imported sass&gt; with module</p>
<p class=\\"imported-less\\">&lt;imported less&gt; with string additionalData</p>
<p class=\\"imported-stylus\\">&lt;imported stylus&gt;</p>
</div>
<script type=\\"module\\">
import './imported.css'
import './imported-with-import.css'
import './imported.sass'
import sassModule from './imported.module.sass'
document
.querySelector('.imported-sass-module')
.classList.add(sassModule['imported-sass-module'])
import './imported.less'
import './imported.styl'
</script>
",
],
"version": 3,
}
`)
})

test('linked css', async () => {
const res = await page.request.get(
new URL('./linked.css', page.url()).href,
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 8 additions & 0 deletions packages/playground/css-sourcemap/index.html
@@ -1,9 +1,17 @@
<link rel="stylesheet" href="./linked.css" />
<link rel="stylesheet" href="./linked-with-import.css" />

<style>
.inline {
color: red;
}
</style>

<div class="wrapper">
<h1>CSS Sourcemap</h1>

<p class="inline">&lt;inline&gt;</p>

<p class="linked">&lt;linked&gt;: no import</p>
<p class="linked-with-import">&lt;linked&gt;: with import</p>

Expand Down
31 changes: 13 additions & 18 deletions packages/vite/src/node/plugins/html.ts
Expand Up @@ -5,7 +5,8 @@ import type {
OutputAsset,
OutputBundle,
OutputChunk,
RollupError
RollupError,
SourceMapInput
} from 'rollup'
import {
cleanUrl,
Expand Down Expand Up @@ -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<string, Array<string>>
Map<string, Array<{ code: string; map?: SourceMapInput }>>
>()

// HTML Proxy Transform result are stored by config
Expand Down Expand Up @@ -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}`)
Expand All @@ -97,15 +98,15 @@ 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())
}
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(
Expand Down Expand Up @@ -284,12 +285,9 @@ export function buildHtmlPlugin(config: ResolvedConfig): Plugin {
.join('')
// <script type="module">...</script>
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
}
Expand Down Expand Up @@ -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"`

Expand All @@ -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
}
Expand Down
23 changes: 15 additions & 8 deletions 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'
Expand Down Expand Up @@ -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)))
)
}
}

Expand Down Expand Up @@ -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 || '/'
Expand All @@ -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 = `${
Expand Down Expand Up @@ -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')
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/server/pluginContainer.ts
Expand Up @@ -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
}
Expand Down

0 comments on commit 47668b5

Please sign in to comment.