Create React aliases for SVG components (#67104)

This commit is contained in:
Hendrik Liebau 2024-06-25 14:29:32 +02:00 committed by GitHub
parent c8925c36db
commit d824059439
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 104 additions and 14 deletions

View file

@ -2276,29 +2276,50 @@ export default async function getBaseWebpackConfig(
}
}
if (!config.images.disableStaticImages) {
const rules = webpackConfig.module?.rules || []
const hasCustomSvg = rules.some(
(rule) =>
rule &&
const rules = webpackConfig.module?.rules || []
const customSvgRule = rules.find(
(rule): rule is webpack.RuleSetRule =>
(rule &&
typeof rule === 'object' &&
rule.loader !== 'next-image-loader' &&
'test' in rule &&
rule.test instanceof RegExp &&
rule.test.test('.svg')
)
rule.test.test('.svg')) ||
false
)
if (customSvgRule && hasAppDir) {
// Create React aliases for SVG components that were transformed using a
// custom webpack config with e.g. the `@svgr/webpack` loader, or the
// `babel-plugin-inline-react-svg` plugin.
rules.push({
test: customSvgRule.test,
oneOf: [
WEBPACK_LAYERS.reactServerComponents,
WEBPACK_LAYERS.serverSideRendering,
WEBPACK_LAYERS.appPagesBrowser,
].map((layer) => ({
issuerLayer: layer,
resolve: {
alias: createRSCAliases(bundledReactChannel, {
reactProductionProfiling,
layer,
isEdgeServer,
}),
},
})),
})
}
if (!config.images.disableStaticImages) {
const nextImageRule = rules.find(
(rule) =>
rule && typeof rule === 'object' && rule.loader === 'next-image-loader'
)
if (
hasCustomSvg &&
nextImageRule &&
nextImageRule &&
typeof nextImageRule === 'object'
) {
if (customSvgRule && nextImageRule && typeof nextImageRule === 'object') {
// Exclude svg if the user already defined it in custom
// webpack config such as `@svgr/webpack` plugin or
// webpack config such as the `@svgr/webpack` loader, or
// the `babel-plugin-inline-react-svg` plugin.
nextImageRule.test = /\.(png|jpg|jpeg|gif|webp|avif|ico|bmp)$/i
}

View file

@ -0,0 +1,9 @@
import { ReactNode } from 'react'
export default function Root({ children }: { children: ReactNode }) {
return (
<html>
<body>{children}</body>
</html>
)
}

View file

@ -0,0 +1,5 @@
import Icon from '../public/test.svg'
export default function Page() {
return <Icon />
}

View file

@ -0,0 +1,25 @@
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
experimental: {
// Enabling PPR to force using the react experimental channel, which
// implements React owner stacks.
ppr: true,
turbo: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
},
webpack(config) {
config.module.rules.push({ test: /\.svg$/, use: '@svgr/webpack' })
return config
},
}
module.exports = nextConfig

View file

@ -0,0 +1,10 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400" preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,400.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
<path d="M0 2000 l0 -2000 2000 0 2000 0 0 2000 0 2000 -2000 0 -2000 0 0
-2000z m2401 118 l396 -693 -398 -3 c-220 -1 -578 -1 -798 0 l-398 3 396 693
c217 380 398 692 401 692 3 0 184 -312 401 -692z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 601 B

View file

@ -0,0 +1,20 @@
import { nextTestSetup } from 'e2e-utils'
describe('react-owner-stacks-svgr', () => {
const { next, isNextStart, isTurbopack } = nextTestSetup({
files: __dirname,
packageJson: { dependencies: { '@svgr/webpack': '8.1.0' } },
})
/* eslint-disable jest/no-standalone-expect */
// Turbopack currently only supports `next dev` and does not support `next
// build`: https://nextjs.org/docs/architecture/turbopack#unsupported-features
;(isNextStart && isTurbopack ? it.skip : it)(
'renders an SVG that is transformed by @svgr/webpack into a React component',
async () => {
const browser = await next.browser('/')
expect(await browser.elementByCss('svg')).toBeDefined()
}
)
/* eslint-enable jest/no-standalone-expect */
})