Skip to content

Commit

Permalink
feat: css sourcemap support during dev (#7173)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Mar 21, 2022
1 parent 68d76c9 commit 38a655f
Show file tree
Hide file tree
Showing 40 changed files with 1,210 additions and 70 deletions.
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>

0 comments on commit 38a655f

Please sign in to comment.