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

Use SWC to compile Next.js core server files #27167

Merged
merged 8 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@
"wait-port": "0.2.2",
"web-streams-polyfill": "2.1.1",
"webpack-bundle-analyzer": "4.3.0",
"worker-loader": "3.0.7"
"worker-loader": "3.0.7",
"@swc/core": "1.2.63"
},
"resolutions": {
"browserslist": "4.16.6",
Expand Down
15 changes: 10 additions & 5 deletions packages/next/client/dev/error-overlay/hot-dev-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
// can be found here:
// https://github.com/facebook/create-react-app/blob/v3.4.1/packages/react-dev-utils/webpackHotDevClient.js

import * as DevOverlay from '@next/react-dev-overlay/lib/client'
import {
register,
onBuildError,
onBuildOk,
onRefresh,
} from '@next/react-dev-overlay/lib/client'
import stripAnsi from 'next/dist/compiled/strip-ansi'
import { addMessageListener } from './eventsource'
import formatWebpackMessages from './format-webpack-messages'
Expand All @@ -43,7 +48,7 @@ import formatWebpackMessages from './format-webpack-messages'
let hadRuntimeError = false
let customHmrEventHandler
export default function connect() {
DevOverlay.register()
register()

addMessageListener((event) => {
// This is the heartbeat event
Expand Down Expand Up @@ -154,7 +159,7 @@ function handleErrors(errors) {
})

// Only show the first error.
DevOverlay.onBuildError(formatted.errors[0])
onBuildError(formatted.errors[0])

// Also log them to the console.
if (typeof console !== 'undefined' && typeof console.error === 'function') {
Expand All @@ -176,9 +181,9 @@ function handleErrors(errors) {
let startLatency = undefined

function onFastRefresh(hasUpdates) {
DevOverlay.onBuildOk()
onBuildOk()
if (hasUpdates) {
DevOverlay.onRefresh()
onRefresh()
}

if (startLatency) {
Expand Down
17 changes: 10 additions & 7 deletions packages/next/client/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import Router, {
PrivateRouteInfo,
} from '../shared/lib/router/router'
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
import * as querystring from '../shared/lib/router/utils/querystring'
import * as envConfig from '../shared/lib/runtime-config'
import {
urlQueryToSearchParams,
assign,
} from '../shared/lib/router/utils/querystring'
import { setConfig } from '../shared/lib/runtime-config'
import { getURL, loadGetInitialProps, NEXT_DATA, ST } from '../shared/lib/utils'
import { Portal } from './portal'
import initHeadManager from './head-manager'
Expand Down Expand Up @@ -79,7 +82,7 @@ const prefix: string = assetPrefix || ''
// So, this is how we do it in the client side at runtime
__webpack_public_path__ = `${prefix}/_next/` //eslint-disable-line
// Initialize next/config with the environment configuration
envConfig.setConfig({
setConfig({
serverRuntimeConfig: {},
publicRuntimeConfig: runtimeConfig || {},
})
Expand Down Expand Up @@ -205,8 +208,8 @@ class Container extends React.Component<{
router.pathname +
'?' +
String(
querystring.assign(
querystring.urlQueryToSearchParams(router.query),
assign(
urlQueryToSearchParams(router.query),
new URLSearchParams(location.search)
)
),
Expand Down Expand Up @@ -257,7 +260,7 @@ class Container extends React.Component<{
export const emitter: MittEmitter<string> = mitt()
let CachedComponent: React.ComponentType

export default async (opts: { webpackHMR?: any } = {}) => {
export async function initNext(opts: { webpackHMR?: any } = {}) {
// This makes sure this specific lines are removed in production
if (process.env.NODE_ENV === 'development') {
webpackHMR = opts.webpackHMR
Expand Down Expand Up @@ -406,7 +409,7 @@ export default async (opts: { webpackHMR?: any } = {}) => {
render(renderCtx)
return emitter
} else {
return { emitter, render, renderCtx }
return { emitter, renderCtx }
}
}

Expand Down
8 changes: 4 additions & 4 deletions packages/next/client/link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Children, useEffect } from 'react'
import React from 'react'
import { UrlObject } from 'url'
import {
addBasePath,
Expand Down Expand Up @@ -232,7 +232,7 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
let child: any
if (process.env.NODE_ENV === 'development') {
try {
child = Children.only(children)
child = React.Children.only(children)
} catch (err) {
throw new Error(
`Multiple children were passed to <Link> with \`href\` of \`${props.href}\` but only one child is supported https://nextjs.org/docs/messages/link-multiple-children` +
Expand All @@ -242,7 +242,7 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
)
}
} else {
child = Children.only(children)
child = React.Children.only(children)
}
const childRef: any = child && typeof child === 'object' && child.ref

Expand All @@ -261,7 +261,7 @@ function Link(props: React.PropsWithChildren<LinkProps>) {
},
[childRef, setIntersectionRef]
)
useEffect(() => {
React.useEffect(() => {
const shouldPrefetch = isVisible && p && isLocalURL(href)
const curLocale =
typeof locale !== 'undefined' ? locale : router && router.locale
Expand Down
25 changes: 18 additions & 7 deletions packages/next/client/next-dev.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
/* globals __REPLACE_NOOP_IMPORT__ */
import initNext, * as next from './'
import { initNext, version, router, emitter, render, renderError } from './'
import EventSourcePolyfill from './dev/event-source-polyfill'
import initOnDemandEntries from './dev/on-demand-entries-client'
import initWebpackHMR from './dev/webpack-hot-middleware-client'
import initializeBuildWatcher from './dev/dev-build-watcher'
import { displayContent } from './dev/fouc'
import { addMessageListener } from './dev/error-overlay/eventsource'
import * as querystring from '../shared/lib/router/utils/querystring'
import {
assign,
urlQueryToSearchParams,
} from '../shared/lib/router/utils/querystring'

// Temporary workaround for the issue described here:
// https://github.com/vercel/next.js/issues/3775#issuecomment-407438123
Expand All @@ -27,9 +30,18 @@ const {
const prefix = assetPrefix || ''
const webpackHMR = initWebpackHMR()

window.next = next
window.next = {
version,
// router is initialized later so it has to be live-binded
get router() {
return router
},
emitter,
render,
renderError,
}
initNext({ webpackHMR })
.then(({ renderCtx, render }) => {
.then(({ renderCtx }) => {
initOnDemandEntries({ assetPrefix: prefix })

let buildIndicatorHandler = () => {}
Expand All @@ -46,7 +58,6 @@ initNext({ webpackHMR })
})
} else if (event.data.indexOf('serverOnlyChanges') !== -1) {
const { pages } = JSON.parse(event.data)
const router = window.next.router

if (!router.clc && pages.includes(router.pathname)) {
console.log('Refreshing page data due to server-side change')
Expand All @@ -60,8 +71,8 @@ initNext({ webpackHMR })
router.pathname +
'?' +
String(
querystring.assign(
querystring.urlQueryToSearchParams(router.query),
assign(
urlQueryToSearchParams(router.query),
new URLSearchParams(location.search)
)
),
Expand Down
13 changes: 11 additions & 2 deletions packages/next/client/next.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import initNext, * as next from './'
import { initNext, version, router, emitter, render, renderError } from './'

window.next = next
window.next = {
version,
// router is initialized later so it has to be live-binded
get router() {
return router
},
emitter,
render,
renderError,
}

initNext().catch(console.error)
3 changes: 2 additions & 1 deletion packages/next/client/page-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import getAssetPathFromRoute from '../shared/lib/router/utils/get-asset-path-fro
import { isDynamicRoute } from '../shared/lib/router/utils/is-dynamic'
import { parseRelativeUrl } from '../shared/lib/router/utils/parse-relative-url'
import { removePathTrailingSlash } from './normalize-trailing-slash'
import createRouteLoader, {
import {
createRouteLoader,
getClientBuildManifest,
RouteLoader,
} from './route-loader'
Expand Down
2 changes: 1 addition & 1 deletion packages/next/client/portal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react'
import React from 'react'
import { createPortal } from 'react-dom'

type PortalProps = {
Expand Down
8 changes: 4 additions & 4 deletions packages/next/client/route-announcer.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React, { useEffect, useState, useRef } from 'react'
import React from 'react'
import { useRouter } from './router'

export function RouteAnnouncer() {
const { asPath } = useRouter()
const [routeAnnouncement, setRouteAnnouncement] = useState('')
const [routeAnnouncement, setRouteAnnouncement] = React.useState('')

// Only announce the path change, but not for the first load because screen reader will do that automatically.
const initialPathLoaded = useRef(false)
const initialPathLoaded = React.useRef(false)

// Every time the path changes, announce the route change. The announcement will be prioritized by h1, then title
// (from metadata), and finally if those don't exist, then the pathName that is in the URL. This methodology is
// inspired by Marcy Sutton's accessible client routing user testing. More information can be found here:
// https://www.gatsbyjs.com/blog/2019-07-11-user-testing-accessible-client-routing/
useEffect(
React.useEffect(
() => {
if (!initialPathLoaded.current) {
initialPathLoaded.current = true
Expand Down
4 changes: 1 addition & 3 deletions packages/next/client/route-loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ function getFilesForRoute(
})
}

function createRouteLoader(assetPrefix: string): RouteLoader {
export function createRouteLoader(assetPrefix: string): RouteLoader {
const entrypoints: Map<
string,
Future<RouteEntrypoint> | RouteEntrypoint
Expand Down Expand Up @@ -423,5 +423,3 @@ function createRouteLoader(assetPrefix: string): RouteLoader {
},
}
}

export default createRouteLoader
7 changes: 5 additions & 2 deletions packages/next/client/router.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* global window */
import React from 'react'
import Router, { NextRouter } from '../shared/lib/router/router'
import Router from '../shared/lib/router/router'
import type { NextRouter } from '../shared/lib/router/router'
import { RouterContext } from '../shared/lib/router-context'

type ClassArguments<T> = T extends new (...args: infer U) => any ? U : any
Expand All @@ -13,7 +14,9 @@ type SingletonRouterBase = {
ready(cb: () => any): void
}

export { Router, NextRouter }
export { Router }

export type { NextRouter }

export type SingletonRouter = SingletonRouterBase & NextRouter

Expand Down
2 changes: 1 addition & 1 deletion packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"requires": [
"./taskfile-ncc.js",
"./taskfile-babel.js",
"./taskfile-typescript.js"
"./taskfile-swc.js"
]
},
"dependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/next/server/next.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ export class NextServer {
const DevServer = require('./dev/next-dev-server').default
return new DevServer(options)
}
return new (await getServerImpl())(options)
const ServerImplementation = await getServerImpl()
return new ServerImplementation(options)
}

private async loadConfig() {
Expand Down
25 changes: 10 additions & 15 deletions packages/next/taskfile-babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const babelClientPresetEnvOptions = {
'transform-typeof-symbol',
'transform-async-to-generator',
'transform-spread',
'proposal-object-rest-spread',
'proposal-dynamic-import',
],
}
Expand All @@ -33,6 +34,15 @@ const babelClientOpts = {
// eslint-disable-next-line no-useless-concat
'@babel/plugin-syntax-dynamic-impor' + 't',
['@babel/plugin-proposal-class-properties', { loose: true }],
[
'@babel/plugin-transform-runtime',
{
corejs: false,
helpers: true,
regenerator: false,
useESModules: false,
},
],
],
overrides: [
{
Expand Down Expand Up @@ -90,21 +100,6 @@ module.exports = function (task) {

const options = {
...babelOpts,
plugins: [
...babelOpts.plugins,
// pages dir doesn't need core-js
serverOrClient === 'client'
? [
'@babel/plugin-transform-runtime',
{
corejs: false,
helpers: true,
regenerator: false,
useESModules: false,
},
]
: false,
].filter(Boolean),
compact: !dev,
babelrc: false,
configFile: false,
Expand Down
Loading