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

devSourcemap: true not generating sourcemaps for preview mode #11480

Closed
7 tasks done
shirotech opened this issue Dec 23, 2022 · 3 comments
Closed
7 tasks done

devSourcemap: true not generating sourcemaps for preview mode #11480

shirotech opened this issue Dec 23, 2022 · 3 comments
Labels
duplicate This issue or pull request already exists

Comments

@shirotech
Copy link

Describe the bug

When running the command vite preview it should be treated as "dev" and hence should produce sourcemaps for easy debugging. even when NODE_ENV and mode is set to "development".

Reproduction

https://stackblitz.com/edit/vitejs-vite-2h4hxn?file=vite.config.ts&terminal=preview

Steps to reproduce

npm run preview

System Info

System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.14.2 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 7.17.0 - /usr/local/bin/npm
  npmPackages:
    vite: ^4.0.0 => 4.0.3

Used Package Manager

npm

Logs

vite v4.0.3 building for development...
✓ 6 modules transformed.
dist/index.html                      0.45 kB
dist/assets/javascript-8dac5379.svg  1.00 kB
dist/assets/index-1bb5262e.css       1.70 kB
dist/assets/index-de04364a.js        2.27 kB │ map: 1.61 kB
  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose

Validations

@sapphi-red
Copy link
Member

css sourcemap for build is not supported yet. Closing as a duplicate of #2830

@sapphi-red sapphi-red closed this as not planned Won't fix, can't repro, duplicate, stale Dec 23, 2022
@sapphi-red sapphi-red added duplicate This issue or pull request already exists and removed pending triage labels Dec 23, 2022
@shirotech
Copy link
Author

@sapphi-red Okay that's cool, but not sure how can a basic and industry standard feature not be supported? There must be some technical limitations? I can try implement it.. is a PR welcomed?

@sapphi-red
Copy link
Member

PR is welcome! This is the related part.

async transform(css, id, options) {
if (
!isCSSRequest(id) ||
commonjsProxyRE.test(id) ||
SPECIAL_QUERY_RE.test(id)
) {
return
}
css = stripBomTag(css)
const inlined = inlineRE.test(id)
const modules = cssModulesCache.get(config)!.get(id)
// #6984, #7552
// `foo.module.css` => modulesCode
// `foo.module.css?inline` => cssContent
const modulesCode =
modules &&
!inlined &&
dataToEsm(modules, { namedExports: true, preferConst: true })
if (config.command === 'serve') {
const getContentWithSourcemap = async (content: string) => {
if (config.css?.devSourcemap) {
const sourcemap = this.getCombinedSourcemap()
await injectSourcesContent(sourcemap, cleanUrl(id), config.logger)
return getCodeWithSourcemap('css', content, sourcemap)
}
return content
}
if (isDirectCSSRequest(id)) {
return await getContentWithSourcemap(css)
}
// server only
if (options?.ssr) {
return modulesCode || `export default ${JSON.stringify(css)}`
}
if (inlined) {
return `export default ${JSON.stringify(css)}`
}
const cssContent = await getContentWithSourcemap(css)
const code = [
`import { updateStyle as __vite__updateStyle, removeStyle as __vite__removeStyle } from ${JSON.stringify(
path.posix.join(config.base, CLIENT_PUBLIC_PATH),
)}`,
`const __vite__id = ${JSON.stringify(id)}`,
`const __vite__css = ${JSON.stringify(cssContent)}`,
`__vite__updateStyle(__vite__id, __vite__css)`,
// css modules exports change on edit so it can't self accept
`${
modulesCode ||
`import.meta.hot.accept()\nexport default __vite__css`
}`,
`import.meta.hot.prune(() => __vite__removeStyle(__vite__id))`,
].join('\n')
return { code, map: { mappings: '' } }
}
// build CSS handling ----------------------------------------------------
// record css
// cache css compile result to map
// and then use the cache replace inline-style-flag when `generateBundle` in vite:build-html plugin
const inlineCSS = inlineCSSRE.test(id)
const isHTMLProxy = htmlProxyRE.test(id)
const query = parseRequest(id)
if (inlineCSS && isHTMLProxy) {
addToHTMLProxyTransformResult(
`${getHash(cleanUrl(id))}_${Number.parseInt(query!.index)}`,
css,
)
return `export default ''`
}
if (!inlined) {
styles.set(id, css)
}
let code: string
if (usedRE.test(id)) {
if (modulesCode) {
code = modulesCode
} else {
let content = css
if (config.build.minify) {
content = await minifyCSS(content, config)
}
code = `export default ${JSON.stringify(content)}`
}
} else {
// if moduleCode exists return it **even if** it does not have `?used`
// this will disable tree-shake to work with `import './foo.module.css'` but this usually does not happen
// this is a limitation of the current approach by `?used` to make tree-shake work
// See #8936 for more details
code = modulesCode || `export default ''`
}
return {
code,
map: { mappings: '' },
// avoid the css module from being tree-shaken so that we can retrieve
// it in renderChunk()
moduleSideEffects: inlined ? false : 'no-treeshake',
}
},
async renderChunk(code, chunk, opts) {
let chunkCSS = ''
let isPureCssChunk = true
const ids = Object.keys(chunk.modules)
for (const id of ids) {
if (
!isCSSRequest(id) ||
cssModuleRE.test(id) ||
commonjsProxyRE.test(id)
) {
isPureCssChunk = false
}
if (styles.has(id)) {
chunkCSS += styles.get(id)
}
}
if (!chunkCSS) {
return null
}
const publicAssetUrlMap = publicAssetUrlCache.get(config)!
// resolve asset URL placeholders to their built file URLs
const resolveAssetUrlsInCss = (
chunkCSS: string,
cssAssetName: string,
) => {
const encodedPublicUrls = encodePublicUrlsInCSS(config)
const relative = config.base === './' || config.base === ''
const cssAssetDirname =
encodedPublicUrls || relative
? getCssAssetDirname(cssAssetName)
: undefined
const toRelative = (filename: string, importer: string) => {
// relative base + extracted CSS
const relativePath = path.posix.relative(cssAssetDirname!, filename)
return relativePath.startsWith('.')
? relativePath
: './' + relativePath
}
// replace asset url references with resolved url.
chunkCSS = chunkCSS.replace(assetUrlRE, (_, fileHash, postfix = '') => {
const filename = this.getFileName(fileHash) + postfix
chunk.viteMetadata.importedAssets.add(cleanUrl(filename))
return toOutputFilePathInCss(
filename,
'asset',
cssAssetName,
'css',
config,
toRelative,
)
})
// resolve public URL from CSS paths
if (encodedPublicUrls) {
const relativePathToPublicFromCSS = path.posix.relative(
cssAssetDirname!,
'',
)
chunkCSS = chunkCSS.replace(publicAssetUrlRE, (_, hash) => {
const publicUrl = publicAssetUrlMap.get(hash)!.slice(1)
return toOutputFilePathInCss(
publicUrl,
'public',
cssAssetName,
'css',
config,
() => `${relativePathToPublicFromCSS}/${publicUrl}`,
)
})
}
return chunkCSS
}
function ensureFileExt(name: string, ext: string) {
return normalizePath(
path.format({ ...path.parse(name), base: undefined, ext }),
)
}
if (config.build.cssCodeSplit) {
if (isPureCssChunk) {
// this is a shared CSS-only chunk that is empty.
pureCssChunks.add(chunk)
}
if (opts.format === 'es' || opts.format === 'cjs') {
const cssAssetName = chunk.facadeModuleId
? normalizePath(path.relative(config.root, chunk.facadeModuleId))
: chunk.name
const lang = path.extname(cssAssetName).slice(1)
const cssFileName = ensureFileExt(cssAssetName, '.css')
chunkCSS = resolveAssetUrlsInCss(chunkCSS, cssAssetName)
chunkCSS = await finalizeCss(chunkCSS, true, config)
// emit corresponding css file
const referenceId = this.emitFile({
name: path.basename(cssFileName),
type: 'asset',
source: chunkCSS,
})
const originalName = isPreProcessor(lang) ? cssAssetName : cssFileName
const isEntry = chunk.isEntry && isPureCssChunk
generatedAssets
.get(config)!
.set(referenceId, { originalName, isEntry })
chunk.viteMetadata.importedCss.add(this.getFileName(referenceId))
} else if (!config.build.ssr) {
// legacy build and inline css
// Entry chunk CSS will be collected into `chunk.viteMetadata.importedCss`
// and injected later by the `'vite:build-html'` plugin into the `index.html`
// so it will be duplicated. (https://github.com/vitejs/vite/issues/2062#issuecomment-782388010)
// But because entry chunk can be imported by dynamic import,
// we shouldn't remove the inlined CSS. (#10285)
chunkCSS = await finalizeCss(chunkCSS, true, config)
let cssString = JSON.stringify(chunkCSS)
cssString =
renderAssetUrlInJS(
this,
config,
chunk,
opts,
cssString,
)?.toString() || cssString
const style = `__vite_style__`
const injectCode =
`var ${style} = document.createElement('style');` +
`${style}.textContent = ${cssString};` +
`document.head.appendChild(${style});`
const wrapIdx = code.indexOf('System.register')
const insertMark = "'use strict';"
const insertIdx = code.indexOf(insertMark, wrapIdx)
const s = new MagicString(code)
s.appendLeft(insertIdx + insertMark.length, injectCode)
if (config.build.sourcemap) {
// resolve public URL from CSS paths, we need to use absolute paths
return {
code: s.toString(),
map: s.generateMap({ hires: true }),
}
} else {
return { code: s.toString() }
}
}
} else {
chunkCSS = resolveAssetUrlsInCss(chunkCSS, cssBundleName)
// finalizeCss is called for the aggregated chunk in generateBundle
outputToExtractedCSSMap.set(
opts,
(outputToExtractedCSSMap.get(opts) || '') + chunkCSS,
)
}
return null
},
augmentChunkHash(chunk) {
if (chunk.viteMetadata?.importedCss.size) {
let hash = ''
for (const id of chunk.viteMetadata.importedCss) {
hash += id
}
return hash
}
},
async generateBundle(opts, bundle) {
// @ts-expect-error asset emits are skipped in legacy bundle
if (opts.__vite_skip_asset_emit__) {
return
}
// remove empty css chunks and their imports
if (pureCssChunks.size) {
// map each pure css chunk (rendered chunk) to it's corresponding bundle
// chunk. we check that by comparing the `moduleIds` as they have different
// filenames (rendered chunk has the !~{XXX}~ placeholder)
const pureCssChunkNames: string[] = []
for (const pureCssChunk of pureCssChunks) {
for (const key in bundle) {
const bundleChunk = bundle[key]
if (
bundleChunk.type === 'chunk' &&
arrayEqual(bundleChunk.moduleIds, pureCssChunk.moduleIds)
) {
pureCssChunkNames.push(key)
break
}
}
}
const emptyChunkFiles = pureCssChunkNames
.map((file) => path.basename(file))
.join('|')
.replace(/\./g, '\\.')
const emptyChunkRE = new RegExp(
opts.format === 'es'
? `\\bimport\\s*["'][^"']*(?:${emptyChunkFiles})["'];\n?`
: `\\brequire\\(\\s*["'][^"']*(?:${emptyChunkFiles})["']\\);\n?`,
'g',
)
for (const file in bundle) {
const chunk = bundle[file]
if (chunk.type === 'chunk') {
// remove pure css chunk from other chunk's imports,
// and also register the emitted CSS files under the importer
// chunks instead.
chunk.imports = chunk.imports.filter((file) => {
if (pureCssChunkNames.includes(file)) {
const {
viteMetadata: { importedCss },
} = bundle[file] as OutputChunk
importedCss.forEach((file) =>
chunk.viteMetadata.importedCss.add(file),
)
return false
}
return true
})
chunk.code = chunk.code.replace(
emptyChunkRE,
// remove css import while preserving source map location
(m) => `/* empty css ${''.padEnd(m.length - 15)}*/`,
)
}
}
const removedPureCssFiles = removedPureCssFilesCache.get(config)!
pureCssChunkNames.forEach((fileName) => {
removedPureCssFiles.set(fileName, bundle[fileName] as RenderedChunk)
delete bundle[fileName]
})
}
let extractedCss = outputToExtractedCSSMap.get(opts)
if (extractedCss && !hasEmitted) {
hasEmitted = true
extractedCss = await finalizeCss(extractedCss, true, config)
this.emitFile({
name: cssBundleName,
type: 'asset',
source: extractedCss,
})
}
},
}
}

@github-actions github-actions bot locked and limited conversation to collaborators Jan 8, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
duplicate This issue or pull request already exists
Projects
None yet
Development

No branches or pull requests

2 participants