Skip to content

Commit

Permalink
fix(react): sourcemap incorrect warning and classic runtime sourcemap (
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Jul 9, 2022
1 parent da7c3ae commit bdae7fa
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/plugin-react/package.json
Expand Up @@ -44,6 +44,7 @@
"@babel/plugin-transform-react-jsx-development": "^7.18.6",
"@babel/plugin-transform-react-jsx-self": "^7.18.6",
"@babel/plugin-transform-react-jsx-source": "^7.18.6",
"magic-string": "^0.26.2",
"react-refresh": "^0.14.0"
},
"peerDependencies": {
Expand Down
29 changes: 25 additions & 4 deletions packages/plugin-react/src/index.ts
Expand Up @@ -3,6 +3,8 @@ import type { ParserOptions, TransformOptions, types as t } from '@babel/core'
import * as babel from '@babel/core'
import { createFilter, normalizePath } from 'vite'
import type { Plugin, PluginOption, ResolvedConfig } from 'vite'
import MagicString from 'magic-string'
import type { SourceMap } from 'magic-string'
import {
addRefreshWrapper,
isRefreshBoundary,
Expand Down Expand Up @@ -88,11 +90,14 @@ declare module 'vite' {
}
}

const prependReactImportCode = "import React from 'react'; "

export default function viteReact(opts: Options = {}): PluginOption[] {
// Provide default values for Rollup compat.
let devBase = '/'
let resolvedCacheDir: string
let filter = createFilter(opts.include, opts.exclude)
let needHiresSourcemap = false

This comment has been minimized.

Copy link
@seivan

seivan Jul 9, 2022

  • needHire
  • needHighRes
  • needHigher
    Also thank you!
let isProduction = true
let projectRoot = process.cwd()
let skipFastRefresh = opts.fastRefresh === false
Expand Down Expand Up @@ -135,6 +140,8 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
filter = createFilter(opts.include, opts.exclude, {
resolve: projectRoot
})
needHiresSourcemap =
config.command === 'build' && !!config.build.sourcemap
isProduction = config.isProduction
skipFastRefresh ||= isProduction || config.command === 'build'

Expand Down Expand Up @@ -217,6 +224,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
}

let ast: t.File | null | undefined
let prependReactImport = false
if (!isProjectFile || isJSX) {
if (useAutomaticRuntime) {
// By reverse-compiling "React.createElement" calls into JSX,
Expand Down Expand Up @@ -261,11 +269,23 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
// Even if the automatic JSX runtime is not used, we can still
// inject the React import for .jsx and .tsx modules.
if (!skipReactImport && !importReactRE.test(code)) {
code = `import React from 'react'; ` + code
prependReactImport = true
}
}
}

let inputMap: SourceMap | undefined
if (prependReactImport) {
if (needHiresSourcemap) {
const s = new MagicString(code)
s.prepend(prependReactImportCode)
code = s.toString()
inputMap = s.generateMap({ hires: true, source: id })
} else {
code = prependReactImportCode + code
}
}

// Plugins defined through this Vite plugin are only applied
// to modules within the project root, but "babel.config.js"
// files can define plugins that need to be applied to every
Expand All @@ -275,10 +295,11 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
!babelOptions.configFile &&
!(isProjectFile && babelOptions.babelrc)

// Avoid parsing if no plugins exist.
if (shouldSkip) {
// Avoid parsing if no plugins exist.
return {
code
code,
map: inputMap ?? null
}
}

Expand Down Expand Up @@ -326,7 +347,7 @@ export default function viteReact(opts: Options = {}): PluginOption[] {
plugins,
sourceMaps: true,
// Vite handles sourcemap flattening
inputSourceMap: false as any
inputSourceMap: inputMap ?? (false as any)
})

if (result) {
Expand Down
8 changes: 8 additions & 0 deletions playground/react-sourcemap/App.jsx
@@ -0,0 +1,8 @@
console.log('App.jsx 1') // for sourcemap
function App() {
return <div>foo</div>
}

console.log('App.jsx 2') // for sourcemap

export default App
7 changes: 7 additions & 0 deletions playground/react-sourcemap/__tests__/react-sourcemap.spec.ts
@@ -0,0 +1,7 @@
import { isBuild, serverLogs } from '~utils'

test.runIf(isBuild)('should not output sourcemap warning', () => {
serverLogs.forEach((log) => {
expect(log).not.toMatch('Sourcemap is likely to be incorrect')
})
})
2 changes: 2 additions & 0 deletions playground/react-sourcemap/index.html
@@ -0,0 +1,2 @@
<div id="app"></div>
<script type="module" src="main.jsx"></script>
9 changes: 9 additions & 0 deletions playground/react-sourcemap/main.jsx
@@ -0,0 +1,9 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'

ReactDOM.createRoot(document.getElementById('app')).render(
React.createElement(App)
)

console.log('main.jsx') // for sourcemap
21 changes: 21 additions & 0 deletions playground/react-sourcemap/package.json
@@ -0,0 +1,21 @@
{
"name": "test-react-sourcemap",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"dev:classic": "cross-env USE_CLASSIC=1 vite",
"build": "vite build",
"build:classic": "cross-env USE_CLASSIC=1 vite build",
"debug": "node --inspect-brk ../../packages/vite/bin/vite",
"preview": "vite preview"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@vitejs/plugin-react": "workspace:*",
"cross-env": "^7.0.3"
}
}
15 changes: 15 additions & 0 deletions playground/react-sourcemap/vite.config.ts
@@ -0,0 +1,15 @@
import react from '@vitejs/plugin-react'
import type { UserConfig } from 'vite'

const config: UserConfig = {
plugins: [
react({
jsxRuntime: process.env.USE_CLASSIC === '1' ? 'classic' : 'automatic'
})
],
build: {
sourcemap: true
}
}

export default config
17 changes: 16 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bdae7fa

Please sign in to comment.