Skip to content

Commit

Permalink
Add Fast Refresh Support
Browse files Browse the repository at this point in the history
  • Loading branch information
Timer committed Apr 19, 2020
1 parent 4619996 commit 62b327c
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 4 deletions.
7 changes: 6 additions & 1 deletion packages/next/build/entries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,12 @@ export function createEntrypoints(
const pageLoaderOpts: ClientPagesLoaderOptions = {
page,
absolutePagePath,
hotRouterUpdates: dev, // Hot router updates only apply in development mode
hotRouterUpdates:
// Hot router updates only apply in development mode
dev &&
// However, React Refresh has its own hot module runtime, so we can't
// let them collide.
config.experimental.reactRefresh !== true,
}
const pageLoader = `next-client-pages-loader?${stringify(
pageLoaderOpts
Expand Down
15 changes: 15 additions & 0 deletions packages/next/build/webpack-config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import ReactRefreshWebpackPlugin from '@next/react-refresh-utils/ReactRefreshWebpackPlugin'
import crypto from 'crypto'
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'
import { readFileSync } from 'fs'
Expand Down Expand Up @@ -151,6 +152,10 @@ export default async function getBaseWebpackConfig(
}
}
}

const hasReactRefresh =
dev && !isServer && config.experimental.reactRefresh === true

const distDir = path.join(dir, config.distDir)
const defaultLoaders = {
babel: {
Expand All @@ -164,6 +169,7 @@ export default async function getBaseWebpackConfig(
babelPresetPlugins,
hasModern: !!config.experimental.modern,
development: dev,
hasReactRefresh,
},
},
// Backwards compat
Expand Down Expand Up @@ -759,12 +765,21 @@ export default async function getBaseWebpackConfig(
},
},
defaultLoaders.babel,
hasReactRefresh
? require.resolve('@next/react-refresh-utils/loader')
: '',
].filter(Boolean)
: hasReactRefresh
? [
defaultLoaders.babel,
require.resolve('@next/react-refresh-utils/loader'),
]
: defaultLoaders.babel,
},
].filter(Boolean),
},
plugins: [
hasReactRefresh && new ReactRefreshWebpackPlugin(),
// This plugin makes sure `output.filename` is used for entry chunks
new ChunkNamesPlugin(),
new webpack.DefinePlugin({
Expand Down
16 changes: 14 additions & 2 deletions packages/next/build/webpack/loaders/next-babel-loader.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import babelLoader from 'next/dist/compiled/babel-loader'
import { basename, join } from 'path'
import hash from 'next/dist/compiled/string-hash'
import { basename, join } from 'path'

// increment 'j' to invalidate cache
// eslint-disable-next-line no-useless-concat
const cacheKey = 'babel-cache-' + 'j' + '-'
const cacheKey = 'babel-cache-' + 'k' + '-'
const nextBabelPreset = require('../../babel/preset')

const getModernOptions = (babelOptions = {}) => {
Expand Down Expand Up @@ -59,6 +59,7 @@ module.exports = babelLoader.custom(babel => {
hasModern: opts.hasModern,
babelPresetPlugins: opts.babelPresetPlugins,
development: opts.development,
hasReactRefresh: opts.hasReactRefresh,
}
const filename = join(opts.cwd, 'noop.js')
const loader = Object.assign(
Expand All @@ -73,6 +74,7 @@ module.exports = babelLoader.custom(babel => {
(opts.hasModern ? '-has-modern' : '') +
'-new-polyfills' +
(opts.development ? '-development' : '-production') +
(opts.hasReactRefresh ? '-react-refresh' : '') +
JSON.stringify(
babel.loadPartialConfig({
filename,
Expand All @@ -95,6 +97,7 @@ module.exports = babelLoader.custom(babel => {
delete loader.pagesDir
delete loader.babelPresetPlugins
delete loader.development
delete loader.hasReactRefresh
return { loader, custom }
},
config(
Expand All @@ -108,6 +111,7 @@ module.exports = babelLoader.custom(babel => {
pagesDir,
babelPresetPlugins,
development,
hasReactRefresh,
},
}
) {
Expand Down Expand Up @@ -135,6 +139,14 @@ module.exports = babelLoader.custom(babel => {

options.plugins = options.plugins || []

if (hasReactRefresh) {
const reactRefreshPlugin = babel.createConfigItem(
[require('react-refresh/babel')],
{ type: 'plugin' }
)
options.plugins.unshift(reactRefreshPlugin)
}

if (!isServer && isPageFile) {
const pageConfigPlugin = babel.createConfigItem(
[require('../../babel/plugins/next-page-config')],
Expand Down
6 changes: 6 additions & 0 deletions packages/next/build/webpack/plugins/build-manifest-plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
CLIENT_STATIC_FILES_PATH,
CLIENT_STATIC_FILES_RUNTIME_MAIN,
CLIENT_STATIC_FILES_RUNTIME_POLYFILLS,
CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH,
IS_BUNDLED_PAGE_REGEX,
ROUTE_NAME_REGEX,
} from '../../../next-server/lib/constants'
Expand Down Expand Up @@ -79,6 +80,11 @@ export default class BuildManifestPlugin {
)
const polyfillFiles: string[] = polyfillChunk ? polyfillChunk.files : []

const reactRefreshChunk = chunks.find(
c => c.name === CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH
)
assetMap.devFiles.push(...(reactRefreshChunk?.files ?? []))

for (const filePath of Object.keys(compilation.assets)) {
const path = filePath.replace(/\\/g, '/')
if (/^static\/development\/dll\//.test(path)) {
Expand Down
2 changes: 2 additions & 0 deletions packages/next/next-server/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const AMP_RENDER_TARGET = '__NEXT_AMP_RENDER_TARGET__'
export const CLIENT_STATIC_FILES_RUNTIME_PATH = `${CLIENT_STATIC_FILES_PATH}/${CLIENT_STATIC_FILES_RUNTIME}`
// static/runtime/main.js
export const CLIENT_STATIC_FILES_RUNTIME_MAIN = `${CLIENT_STATIC_FILES_RUNTIME_PATH}/main.js`
// static/runtime/react-refresh.js
export const CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH = `${CLIENT_STATIC_FILES_RUNTIME_PATH}/react-refresh.js`
// static/runtime/amp.js
export const CLIENT_STATIC_FILES_RUNTIME_AMP = `${CLIENT_STATIC_FILES_RUNTIME_PATH}/amp.js`
// static/runtime/webpack.js
Expand Down
1 change: 1 addition & 0 deletions packages/next/next-server/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const defaultConfig: { [key: string]: any } = {
sassOptions: {},
pageEnv: false,
measureFid: false,
reactRefresh: false,
},
future: {
excludeDefaultMomentLocales: false,
Expand Down
2 changes: 2 additions & 0 deletions packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"@babel/preset-typescript": "7.7.2",
"@babel/runtime": "7.7.2",
"@babel/types": "7.7.4",
"@next/react-refresh-utils": "9.3.6-canary.3",
"babel-plugin-syntax-jsx": "6.18.0",
"babel-plugin-transform-define": "2.0.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
Expand All @@ -92,6 +93,7 @@
"prop-types": "15.7.2",
"prop-types-exact": "1.2.0",
"react-is": "16.8.6",
"react-refresh": "0.8.1",
"resolve-url-loader": "3.1.1",
"sass-loader": "8.0.2",
"style-loader": "1.0.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/next/server/hot-reloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { recursiveDelete } from '../lib/recursive-delete'
import {
BLOCKED_PAGES,
CLIENT_STATIC_FILES_RUNTIME_AMP,
CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH,
IS_BUNDLED_PAGE_REGEX,
ROUTE_NAME_REGEX,
} from '../next-server/lib/constants'
Expand Down Expand Up @@ -268,6 +269,10 @@ export default class HotReloader {
join(NEXT_PROJECT_ROOT_DIST_CLIENT, 'dev', 'amp-dev')
)

additionalClientEntrypoints[
CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH
] = require.resolve(`@next/react-refresh-utils/runtime`)

return Promise.all([
getBaseWebpackConfig(this.dir, {
dev: true,
Expand Down Expand Up @@ -489,7 +494,7 @@ export default class HotReloader {
pagesDir: this.pagesDir,
reload: this.reload.bind(this),
pageExtensions: this.config.pageExtensions,
hotRouterUpdates: true,
hotRouterUpdates: this.config.experimental.reactRefresh !== true,
...(this.config.onDemandEntries as {
maxInactiveAge: number
pagesBufferLength: number
Expand Down

0 comments on commit 62b327c

Please sign in to comment.