Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: css sourcemap support during dev #7173

Merged
merged 29 commits into from Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
732c3bc
feat(dev): css sourcemap
sapphi-red Feb 26, 2022
38c0052
feat(dev): sass sourcemap
sapphi-red Feb 27, 2022
32090d9
feat(dev): less sourcemap
sapphi-red Feb 27, 2022
55077e3
feat(dev): stylus sourcemap
sapphi-red Feb 27, 2022
64742be
dx: add css sourcemap debug output
sapphi-red Feb 27, 2022
34f138d
fix(dev): direct css request source map
sapphi-red Feb 28, 2022
31730b2
feat: vue sfc css sourcemap
sapphi-red Mar 2, 2022
91d8bf5
fix: css additional data sourcemap
sapphi-red Mar 2, 2022
13c0bb6
refactor: move genSourceMapUrl function
sapphi-red Mar 4, 2022
3e54315
fix: better approach for windows hack
sapphi-red Mar 4, 2022
215c9e9
test: move sourcemap test
sapphi-red Mar 6, 2022
287cceb
test: css sourcemap
sapphi-red Mar 6, 2022
e041930
test: sass sourcemap
sapphi-red Mar 6, 2022
5201c1f
test: less sourcemap
sapphi-red Mar 6, 2022
6f7569b
test: stylus sourcemap
sapphi-red Mar 6, 2022
f3d4461
test: css additional data sourcemap
sapphi-red Mar 6, 2022
da08d19
test: vue sfc style sourcemap
sapphi-red Mar 6, 2022
15c7f35
chore: merge main branch
sapphi-red Mar 6, 2022
3311d00
fix: rewrite .at(-1)
sapphi-red Mar 6, 2022
add2cd6
fix: linux sourcemap path escape
sapphi-red Mar 6, 2022
5607a24
test: ignore no test for serve only test file
sapphi-red Mar 6, 2022
4ca19b0
test: change toMatchSnapshot to toMatchInlineSnapshot
sapphi-red Mar 6, 2022
0f56319
fix: sourcemap warning with plain css
sapphi-red Mar 6, 2022
7e52db0
test: add sourcemap warning test
sapphi-red Mar 6, 2022
9b02811
chore: merge main branch
sapphi-red Mar 12, 2022
59dff9e
refactor: use type assertions if it is legal
sapphi-red Mar 12, 2022
5b0d47b
refactor: rewrite RawSourceMap type
sapphi-red Mar 13, 2022
8e479d3
refactor: remove unused imports
sapphi-red Mar 13, 2022
a1e03f7
feat: return sourcemap with additionalData
sapphi-red Mar 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions packages/playground/css-sourcemap/__tests__/build.spec.ts
@@ -0,0 +1,13 @@
import { isBuild } from 'testUtils'

if (isBuild) {
test('should not output sourcemap warning (#4939)', () => {
serverLogs.forEach((log) => {
expect(log).not.toMatch('Sourcemap is likely to be incorrect')
})
})
} else {
test('this file only includes test for build', () => {
expect(true).toBe(true)
})
}
214 changes: 214 additions & 0 deletions packages/playground/css-sourcemap/__tests__/serve.spec.ts
@@ -0,0 +1,214 @@
import { fromComment } from 'convert-source-map'
import { URL } from 'url'
import { normalizePath } from 'vite'
import { isBuild, testDir } from 'testUtils'

if (!isBuild) {
const root = normalizePath(testDir)

const getStyleTagContentIncluding = async (content: string) => {
const styles = await page.$$('style')
for (const style of styles) {
const text = await style.textContent()
if (text.includes(content)) {
return text
}
}
throw new Error('Not found')
}

const extractSourcemap = (content: string) => {
const lines = content.trim().split('\n')
return fromComment(lines[lines.length - 1]).toObject()
}

const formatSourcemapForSnapshot = (map: any) => {
const m = { ...map }
delete m.file
delete m.names
m.sources = m.sources.map((source) => source.replace(root, '/root'))
return m
}

test('linked css', async () => {
const res = await page.request.get(
new URL('./linked.css', page.url()).href,
{
headers: {
accept: 'text/css'
}
}
)
const css = await res.text()
const lines = css.split('\n')
expect(lines[lines.length - 1].includes('/*')).toBe(false) // expect no sourcemap
})

test('linked css with import', async () => {
const res = await page.request.get(
new URL('./linked-with-import.css', page.url()).href,
{
headers: {
accept: 'text/css'
}
}
)
const css = await res.text()
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ",
"sources": Array [
"/root/be-imported.css",
"/root/linked-with-import.css",
],
"sourcesContent": Array [
".be-imported {
color: red;
}
",
"@import '@/be-imported.css';
.linked-with-import {
color: red;
}
",
],
"version": 3,
}
`)
})

test('imported css', async () => {
const css = await getStyleTagContentIncluding('.imported ')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AAAA,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;AACb,CAAC;",
"sources": Array [
"/root/imported.css",
],
"sourcesContent": Array [
".imported {
color: red;
}
",
],
"version": 3,
}
`)
})

test('imported css with import', async () => {
const css = await getStyleTagContentIncluding('.imported-with-import ')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AAAA;EACE,UAAU;AACZ;;ACAA;EACE,UAAU;AACZ",
"sources": Array [
"/root/be-imported.css",
"/root/imported-with-import.css",
],
"sourcesContent": Array [
".be-imported {
color: red;
}
",
"@import '@/be-imported.css';
.imported-with-import {
color: red;
}
",
],
"version": 3,
}
`)
})

test('imported sass', async () => {
const css = await getStyleTagContentIncluding('.imported-sass ')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AACE;EACE",
"sources": Array [
"/root/imported.sass",
],
"sourcesContent": Array [
".imported
&-sass
color: red
",
],
"version": 3,
}
`)
})

test('imported sass module', async () => {
const css = await getStyleTagContentIncluding('._imported-sass-module_')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AACE;EACE",
"sources": Array [
"/root/imported.module.sass",
],
"sourcesContent": Array [
".imported
&-sass-module
color: red
",
],
"version": 3,
}
`)
})

test('imported less', async () => {
const css = await getStyleTagContentIncluding('.imported-less ')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AACE;EACE",
"sources": Array [
"/root/imported.less",
],
"sourcesContent": Array [
".imported {
&-less {
color: @color;
}
}
",
],
"version": 3,
}
`)
})

test('imported stylus', async () => {
const css = await getStyleTagContentIncluding('.imported-stylus ')
const map = extractSourcemap(css)
expect(formatSourcemapForSnapshot(map)).toMatchInlineSnapshot(`
Object {
"mappings": "AACE;EACE,cAAM",
"sources": Array [
"/root/imported.styl",
],
"sourcesContent": Array [
".imported
&-stylus
color blue-red-mixed
",
],
"version": 3,
}
`)
})
} else {
test('this file only includes test for serve', () => {
expect(true).toBe(true)
})
}
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/be-imported.css
@@ -0,0 +1,3 @@
.be-imported {
color: red;
}
5 changes: 5 additions & 0 deletions packages/playground/css-sourcemap/imported-with-import.css
@@ -0,0 +1,5 @@
@import '@/be-imported.css';

.imported-with-import {
color: red;
}
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/imported.css
@@ -0,0 +1,3 @@
.imported {
color: red;
}
5 changes: 5 additions & 0 deletions packages/playground/css-sourcemap/imported.less
@@ -0,0 +1,5 @@
.imported {
&-less {
color: @color;
}
}
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/imported.module.sass
@@ -0,0 +1,3 @@
.imported
&-sass-module
color: red
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/imported.sass
@@ -0,0 +1,3 @@
.imported
&-sass
color: red
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/imported.styl
@@ -0,0 +1,3 @@
.imported
&-stylus
color blue-red-mixed
35 changes: 35 additions & 0 deletions packages/playground/css-sourcemap/index.html
@@ -0,0 +1,35 @@
<link rel="stylesheet" href="./linked.css" />
<link rel="stylesheet" href="./linked-with-import.css" />

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

<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>
5 changes: 5 additions & 0 deletions packages/playground/css-sourcemap/linked-with-import.css
@@ -0,0 +1,5 @@
@import '@/be-imported.css';

.linked-with-import {
color: red;
}
3 changes: 3 additions & 0 deletions packages/playground/css-sourcemap/linked.css
@@ -0,0 +1,3 @@
.linked {
color: red;
}
18 changes: 18 additions & 0 deletions packages/playground/css-sourcemap/package.json
@@ -0,0 +1,18 @@
{
"name": "test-css-sourcemap",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"debug": "node --inspect-brk ../../vite/bin/vite",
"preview": "vite preview"
},
"devDependencies": {
"convert-source-map": "^1.8.0",
"less": "^4.1.2",
"magic-string": "^0.25.7",
"sass": "^1.43.4",
"stylus": "^0.55.0"
}
}
40 changes: 40 additions & 0 deletions packages/playground/css-sourcemap/vite.config.js
@@ -0,0 +1,40 @@
const MagicString = require('magic-string')

/**
* @type {import('vite').UserConfig}
*/
module.exports = {
resolve: {
alias: {
'@': __dirname
}
},
css: {
preprocessorOptions: {
less: {
additionalData: '@color: red;'
},
styl: {
additionalData: (content, filename) => {
const ms = new MagicString(content, { filename })

const willBeReplaced = 'blue-red-mixed'
const start = content.indexOf(willBeReplaced)
ms.overwrite(start, start + willBeReplaced.length, 'purple')

const map = ms.generateMap({ hires: true })
map.file = filename
map.sources = [filename]

return {
content: ms.toString(),
map
}
}
}
}
},
build: {
sourcemap: true
}
}
23 changes: 23 additions & 0 deletions packages/playground/vue-sourcemap/Css.vue
@@ -0,0 +1,23 @@
<template>
<p class="css">&lt;css&gt;</p>
<p :class="$style['css-module']">&lt;css&gt; module</p>
<p class="css-scoped">&lt;css&gt; scoped</p>
</template>

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

<style module>
.css-module {
color: red;
}
</style>

<style scoped>
.css-scoped {
color: red;
}
</style>