1
0
mirror of synced 2025-12-19 18:11:23 -05:00

Fix webpack 5 support (Webpack 5 now used by default) (patch) (#2453)

Co-authored-by: Kristoffer K. <merceyz@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Brandon Bayer
2021-06-08 13:31:52 -04:00
committed by GitHub
parent ff85cf1c17
commit a510bd079b
22 changed files with 201 additions and 281 deletions

View File

@@ -26,9 +26,9 @@ jobs:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
**/node_modules
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v9-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v10-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ runner.node_version}}-yarn-v9-
${{ runner.os }}-${{ runner.node_version}}-yarn-v10-
- name: Install dependencies
run: yarn install --frozen-lockfile --silent
env:
@@ -72,9 +72,9 @@ jobs:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
**/node_modules
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v9-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v10-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ runner.node_version}}-yarn-v9-
${{ runner.os }}-${{ runner.node_version}}-yarn-v10-
- run: yarn install --frozen-lockfile --check-files
- name: Build Packages
run: yarn build
@@ -140,9 +140,9 @@ jobs:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
**/node_modules
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v9-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v10-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ runner.node_version}}-yarn-v9-
${{ runner.os }}-${{ runner.node_version}}-yarn-v10-
- run: yarn install --frozen-lockfile --check-files
# - run: yarn cpy node_modules/.blitz packages/core/node_modules/.blitz
# if: matrix.os == 'windows-latest'
@@ -335,6 +335,7 @@ jobs:
env:
NEXT_TELEMETRY_DISABLED: 1
NEXT_TEST_JOB: 1
NEXT_TEST_LEGACY_REACT: 1
HEADLESS: true
steps:
@@ -375,9 +376,9 @@ jobs:
**/node_modules
/home/runner/.cache/Cypress
C:\Users\runneradmin\AppData\Local\Cypress\Cache
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v9-${{ hashFiles('yarn.lock') }}
key: ${{ runner.os }}-${{ runner.node_version}}-yarn-v10-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ runner.node_version}}-yarn-v9-
${{ runner.os }}-${{ runner.node_version}}-yarn-v10-
- run: yarn install --check-files
if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }}

View File

@@ -20,3 +20,6 @@ bin
packages/generator/templates/**
.github/ISSUE_TEMPLATE/bug_report.md
nextjs/packages/next/compiled/**
// Because file from nextjs upstream isn't formatted properly
nextjs/packages/next/build/webpack-config.ts

View File

@@ -1,10 +1,17 @@
import {Link, BlitzPage, InferGetStaticPropsType} from "blitz"
import getProducts, {averagePrice} from "../../queries/getProducts"
import getProducts from "../../queries/getProducts"
import {sum} from "lodash"
import {Product} from "@prisma/client"
// regression test for #1646
import {getMeSomeQualityHumor} from "../../api"
console.log("Attention! Must read: " + getMeSomeQualityHumor())
export function averagePrice(products: Product[]) {
const prices = products.map((p) => p.price ?? 0)
return sum(prices) / prices.length
}
export const getStaticProps = async () => {
const {products} = await getProducts({orderBy: {id: "desc"}})
return {

View File

@@ -1,11 +1,5 @@
import {Middleware, paginate} from "blitz"
import db, {Prisma, Product} from "db"
import {sum} from "lodash"
export function averagePrice(products: Product[]) {
const prices = products.map((p) => p.price ?? 0)
return sum(prices) / prices.length
}
import db, {Prisma} from "db"
type GetProductsInput = {
where?: Prisma.ProductFindManyArgs["where"]

View File

@@ -16,3 +16,6 @@ packages/next-codemod/**/*.js
packages/next-codemod/**/*.d.ts
packages/next-env/**/*.d.ts
test-timings.json
// Because file from nextjs upstream isn't formatted properly
nextjs/packages/next/build/webpack-config.ts

View File

@@ -52,6 +52,20 @@ import WebpackConformancePlugin, {
} from './webpack/plugins/webpack-conformance-plugin'
import { WellKnownErrorsPlugin } from './webpack/plugins/wellknown-errors-plugin'
import fs from 'fs'
import { getProjectRoot } from '../server/lib/utils'
/* ------ Blitz.js ------- */
function doesDbModuleExist() {
const projectRoot = getProjectRoot()
return (
fs.existsSync(path.join(projectRoot, 'db/index.js')) ||
fs.existsSync(path.join(projectRoot, 'db/index.ts')) ||
fs.existsSync(path.join(projectRoot, 'db/index.tsx'))
)
}
/* ------ Blitz.js ------- */
type ExcludesFalse = <T>(x: T | false) => x is T
const devtoolRevertWarning = execOnce(
@@ -882,6 +896,9 @@ export default async function getBaseWebpackConfig(
entry: async () => {
return {
...(clientEntries ? clientEntries : {}),
...(isServer && doesDbModuleExist()
? { 'blitz-db': './db/index' }
: {}),
...entrypoints,
}
},
@@ -997,6 +1014,24 @@ export default async function getBaseWebpackConfig(
]
: defaultLoaders.babel,
},
...(isServer
? []
: [
{
issuer: /(mutations|queries)(?!.*\.client)/,
resource: /_resolvers/,
use: { loader: require.resolve('null-loader') },
},
// Because of packages/core/src/prisma-utils.ts
{
test: /[\\/]npm-which[\\/]/,
use: { loader: require.resolve('null-loader') },
},
{
test: /[\\/]cross-spawn[\\/]/,
use: { loader: require.resolve('null-loader') },
},
]),
].filter(Boolean),
},
plugins: [
@@ -1556,93 +1591,94 @@ export default async function getBaseWebpackConfig(
// Patch `@zeit/next-sass`, `@zeit/next-less`, `@zeit/next-stylus` for compatibility
if (webpackConfig.module && Array.isArray(webpackConfig.module.rules)) {
;[].forEach.call(webpackConfig.module.rules, function (
rule: webpack.RuleSetRule
) {
if (!(rule.test instanceof RegExp && Array.isArray(rule.use))) {
return
}
const isSass =
rule.test.source === '\\.scss$' || rule.test.source === '\\.sass$'
const isLess = rule.test.source === '\\.less$'
const isCss = rule.test.source === '\\.css$'
const isStylus = rule.test.source === '\\.styl$'
// Check if the rule we're iterating over applies to Sass, Less, or CSS
if (!(isSass || isLess || isCss || isStylus)) {
return
}
;[].forEach.call(rule.use, function (use: webpack.RuleSetUseItem) {
if (
!(
use &&
typeof use === 'object' &&
// Identify use statements only pertaining to `css-loader`
(use.loader === 'css-loader' ||
use.loader === 'css-loader/locals') &&
use.options &&
typeof use.options === 'object' &&
// The `minimize` property is a good heuristic that we need to
// perform this hack. The `minimize` property was only valid on
// old `css-loader` versions. Custom setups (that aren't next-sass,
// next-less or next-stylus) likely have the newer version.
// We still handle this gracefully below.
(Object.prototype.hasOwnProperty.call(use.options, 'minimize') ||
Object.prototype.hasOwnProperty.call(
use.options,
'exportOnlyLocals'
))
)
) {
;[].forEach.call(
webpackConfig.module.rules,
function (rule: webpack.RuleSetRule) {
if (!(rule.test instanceof RegExp && Array.isArray(rule.use))) {
return
}
// Try to monkey patch within a try-catch. We shouldn't fail the build
// if we cannot pull this off.
// The user may not even be using the `next-sass` or `next-less` or
// `next-stylus` plugins.
// If it does work, great!
try {
// Resolve the version of `@zeit/next-css` as depended on by the Sass,
// Less or Stylus plugin.
const correctNextCss = require.resolve('@zeit/next-css', {
paths: [
isCss
? // Resolve `@zeit/next-css` from the base directory
dir
: // Else, resolve it from the specific plugins
require.resolve(
isSass
? '@zeit/next-sass'
: isLess
? '@zeit/next-less'
: isStylus
? '@zeit/next-stylus'
: 'next'
),
],
})
const isSass =
rule.test.source === '\\.scss$' || rule.test.source === '\\.sass$'
const isLess = rule.test.source === '\\.less$'
const isCss = rule.test.source === '\\.css$'
const isStylus = rule.test.source === '\\.styl$'
// If we found `@zeit/next-css` ...
if (correctNextCss) {
// ... resolve the version of `css-loader` shipped with that
// package instead of whichever was hoisted highest in your
// `node_modules` tree.
const correctCssLoader = require.resolve(use.loader, {
paths: [correctNextCss],
})
if (correctCssLoader) {
// We saved the user from a failed build!
use.loader = correctCssLoader
}
}
} catch (_) {
// The error is not required to be handled.
// Check if the rule we're iterating over applies to Sass, Less, or CSS
if (!(isSass || isLess || isCss || isStylus)) {
return
}
})
})
;[].forEach.call(rule.use, function (use: webpack.RuleSetUseItem) {
if (
!(
use &&
typeof use === 'object' &&
// Identify use statements only pertaining to `css-loader`
(use.loader === 'css-loader' ||
use.loader === 'css-loader/locals') &&
use.options &&
typeof use.options === 'object' &&
// The `minimize` property is a good heuristic that we need to
// perform this hack. The `minimize` property was only valid on
// old `css-loader` versions. Custom setups (that aren't next-sass,
// next-less or next-stylus) likely have the newer version.
// We still handle this gracefully below.
(Object.prototype.hasOwnProperty.call(use.options, 'minimize') ||
Object.prototype.hasOwnProperty.call(
use.options,
'exportOnlyLocals'
))
)
) {
return
}
// Try to monkey patch within a try-catch. We shouldn't fail the build
// if we cannot pull this off.
// The user may not even be using the `next-sass` or `next-less` or
// `next-stylus` plugins.
// If it does work, great!
try {
// Resolve the version of `@zeit/next-css` as depended on by the Sass,
// Less or Stylus plugin.
const correctNextCss = require.resolve('@zeit/next-css', {
paths: [
isCss
? // Resolve `@zeit/next-css` from the base directory
dir
: // Else, resolve it from the specific plugins
require.resolve(
isSass
? '@zeit/next-sass'
: isLess
? '@zeit/next-less'
: isStylus
? '@zeit/next-stylus'
: 'next'
),
],
})
// If we found `@zeit/next-css` ...
if (correctNextCss) {
// ... resolve the version of `css-loader` shipped with that
// package instead of whichever was hoisted highest in your
// `node_modules` tree.
const correctCssLoader = require.resolve(use.loader, {
paths: [correctNextCss],
})
if (correctCssLoader) {
// We saved the user from a failed build!
use.loader = correctCssLoader
}
}
} catch (_) {
// The error is not required to be handled.
}
})
}
)
}
// Backwards compat for `main.js` entry key

View File

@@ -120,7 +120,7 @@ export const defaultConfig: NextConfig = {
serialWebpackBuild: false,
turboMode: false,
eslint: false,
reactRoot: Number(process.env.NEXT_PRIVATE_REACT_ROOT) > 0,
reactRoot: process.env.NEXT_TEST_LEGACY_REACT ? false : true,
enableBlurryPlaceholder: false,
disableOptimizedLoading: true,
gzipSize: true,

View File

@@ -91,6 +91,7 @@
"node-fetch": "2.6.1",
"node-html-parser": "1.4.9",
"node-libs-browser": "^2.2.1",
"null-loader": "4.0.1",
"os-browserify": "0.3.0",
"p-limit": "3.1.0",
"path-browserify": "1.0.1",

View File

@@ -1,3 +1,6 @@
import fs from 'fs'
import path from 'path'
export function printAndExit(message: string, code = 1) {
if (code === 0) {
console.log(message)
@@ -12,3 +15,17 @@ export function getNodeOptionsWithoutInspect() {
const NODE_INSPECT_RE = /--inspect(-brk)?(=\S+)?( |$)/
return (process.env.NODE_OPTIONS || '').replace(NODE_INSPECT_RE, '')
}
export function getProjectRoot() {
return path.dirname(getConfigSrcPath())
}
export function getConfigSrcPath() {
const tsPath = path.resolve(path.join(process.cwd(), 'blitz.config.ts'))
if (fs.existsSync(tsPath)) {
return tsPath
} else {
const jsPath = path.resolve(path.join(process.cwd(), 'blitz.config.js'))
return jsPath
}
}

View File

@@ -132,7 +132,7 @@ describe('Build Output', () => {
expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 69.5 : 215, 1)
expect(err404FirstLoad.endsWith('kB')).toBe(true)
expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 66.4 : 206, 1)
expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 66.5 : 206, 1)
expect(sharedByAll.endsWith('kB')).toBe(true)
const appSizeValue = _appSize.endsWith('kB')
@@ -149,7 +149,7 @@ describe('Build Output', () => {
true
)
expect(parseFloat(mainSize)).toBeCloseTo(gz ? 19.5 : 60.6, 1)
expect(parseFloat(mainSize)).toBeCloseTo(gz ? 19.6 : 60.7, 1)
expect(mainSize.endsWith('kB')).toBe(true)
expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 44.9 : 142, 1)

View File

@@ -85,6 +85,6 @@ describe('Production response size', () => {
const delta = responseSizesBytes / 1024
// Expected difference: < 0.5
expect(delta).toBeCloseTo(298, 0)
expect(delta).toBeCloseTo(298.6, 0)
})
})

View File

@@ -0,0 +1 @@
module.exports = {}

View File

@@ -7,11 +7,13 @@
"test": "jest --passWithNoTests",
"test:watch": "jest --watch"
},
"browser": "index-browser.js",
"main": "dist/blitzjs-config.cjs.js",
"module": "dist/blitzjs-config.esm.js",
"types": "dist/blitzjs-config.cjs.d.ts",
"files": [
"dist"
"dist",
"index-browser.js"
],
"keywords": [
"next.config.js",

View File

@@ -45,10 +45,14 @@ export interface BlitzConfigNormalized extends BlitzConfig {
}
export function getProjectRoot() {
// TODO consolidate with nextjs/packages/next/server/lib/utils.ts
// IF THIS IS UPDATED, so does the one inside nextjs
return path.dirname(getConfigSrcPath())
}
export function getConfigSrcPath() {
// TODO consolidate with nextjs/packages/next/server/lib/utils.ts
// IF THIS IS UPDATED, so does the one inside nextjs
const tsPath = path.resolve(path.join(process.cwd(), "blitz.config.ts"))
if (existsSync(tsPath)) {
return tsPath

View File

@@ -16,8 +16,7 @@
"head.ts",
"image.ts",
"index.ts",
"server/index.ts",
"with-blitz.ts"
"server/index.ts"
]
},
"main": "dist/blitzjs-core.cjs.js",
@@ -31,8 +30,7 @@
"dynamic",
"head",
"image",
"server",
"with-blitz"
"server"
],
"dependencies": {
"@blitzjs/config": "0.36.4",

View File

@@ -52,7 +52,7 @@ process.nextTick(getConfig)
const getDb = () => {
const projectRoot = getProjectRoot()
const path = join(projectRoot, ".next/blitz/db.js")
const path = join(projectRoot, ".next/server/blitz-db.js")
// eslint-disable-next-line no-eval -- block webpack from following this module path
return eval("require")(path).default
}

View File

@@ -28,7 +28,7 @@ export const fixNodeFileTrace = () => {
const path = require("path")
path.resolve("next.config.js")
path.resolve(".blitz/blitz.config.js")
path.resolve(".next/blitz/db.js")
path.resolve(".next/server/blitz-db.js")
}
export const withFixNodeFileTrace = (fn: Function) => {
fixNodeFileTrace()

View File

@@ -1,48 +0,0 @@
jest.mock("@blitzjs/config", () => {
return {
getConfig: jest.fn().mockReturnValue({}),
}
})
import {withBlitz} from "./with-blitz"
describe("withBlitz", () => {
it("alters the webpack config as expected", () => {
const nextConfigFn = withBlitz({
foo: "bar",
})
const newNext = nextConfigFn("", {defaultConfig: {}})
const newNextWithoutWebpack = Object.assign({}, newNext, {
webpack: null,
webpackDevMiddleware: null,
})
expect(newNextWithoutWebpack).toStrictEqual({
foo: "bar",
experimental: {
reactRoot: true,
},
webpack: null,
webpackDevMiddleware: null,
})
})
it("can handle functional next configs", () => {
const nextConfigFn = withBlitz((phase: any) => ({phase, foo: "bar"}))
const newNext = nextConfigFn("foo", {defaultConfig: {}})
const newNextWithoutWebpack = Object.assign({}, newNext, {
webpack: null,
webpackDevMiddleware: null,
})
expect(newNextWithoutWebpack).toStrictEqual({
phase: "foo",
foo: "bar",
experimental: {
reactRoot: true,
},
webpack: null,
webpackDevMiddleware: null,
})
})
})

View File

@@ -1,113 +0,0 @@
/* eslint-disable es5/no-es6-methods -- file only used on the server */
import {getProjectRoot} from "@blitzjs/config"
import fs from "fs"
import path from "path"
export function withBlitz(nextConfig: any) {
return (phase: string, nextOpts: any = {}) => {
// Need to grab the normalized config based on the phase
// we are in incase we are given a functional config to extend
const normalizedConfig =
typeof nextConfig === "function" ? nextConfig(phase, nextOpts) : nextConfig
const experimental = {
...normalizedConfig.experimental,
}
if (experimental.reactMode === undefined && experimental.reactRoot === undefined) {
// Default to true
experimental.reactRoot = true
}
const newConfig = Object.assign({}, normalizedConfig, {
experimental,
webpack(config: any, options: {isServer: boolean; webpack: any}) {
// ----------------------
// Set up resolve aliases
// ----------------------
// config.resolve ??= {}
// config.resolve.alias ??= {}
// for (const [from, to] of Object.entries(resolveAliases.webpack)) {
// config.resolve.alias[from] = to
// }
if (options.isServer) {
const originalEntry = config.entry
config.entry = async () => ({
...(await originalEntry()),
...(doesDbModuleExist() ? {"../blitz/db": "./db/index"} : {}),
})
} else {
config.module = config.module ?? {}
config.module.rules = config.module.rules ?? []
const excluded = [
/[\\/]npm-which[\\/]/,
/[\\/]cross-spawn[\\/]/,
/@blitzjs[\\/]config/,
/blitz[\\/]packages[\\/]config/,
/blitz2[\\/]packages[\\/]config/,
]
excluded.forEach((excluded) => {
config.module.rules.push({test: excluded, use: {loader: "null-loader"}})
})
if (normalizedConfig.experimental?.isomorphicResolverImports) {
config.module.rules.push({
test: /@blitzjs[\\/]core[\\/]server/,
use: {loader: "null-loader"},
})
config.module.rules.push({
test: /blitz[\\/]packages[\\/]core[\\/]server/,
use: {loader: "null-loader"},
})
config.plugins.push(
new options.webpack.NormalModuleReplacementPlugin(
/[/\\]?(mutations|queries)[/\\]/,
(resource: any) => {
const request = resource.request as string
if (request.includes("_resolvers")) {
return
}
if (
request.endsWith(".js") ||
request.endsWith(".ts") ||
request.endsWith(".jsx") ||
request.endsWith(".tsx")
) {
return
}
resource.request = resource.request + ".client"
},
),
)
} else {
config.module.rules.push({
issuer: /(mutations|queries)(?!.*\.client)/,
resource: /_resolvers/,
use: {loader: "null-loader"},
})
}
}
if (typeof normalizedConfig.webpack === "function") {
return normalizedConfig.webpack(config, options)
}
return config
},
})
function doesDbModuleExist() {
const projectRoot = getProjectRoot()
return (
fs.existsSync(path.join(projectRoot, "db/index.js")) ||
fs.existsSync(path.join(projectRoot, "db/index.ts")) ||
fs.existsSync(path.join(projectRoot, "db/index.tsx"))
)
}
return newConfig
}
}

View File

@@ -1,5 +0,0 @@
{
"main": "dist/blitzjs-core-with-blitz.cjs.js",
"module": "dist/blitzjs-core-with-blitz.esm.js",
"types": "dist/blitzjs-core-with-blitz.d.ts"
}

View File

@@ -42,9 +42,8 @@ export const createStageConfig: Stage = ({config, processNewFile, processNewChil
cwd: config.src,
path: resolve(config.src, "next.config.js"),
contents: Buffer.from(`
const {withBlitz} = require('@blitzjs/core/with-blitz');
const config = require('../blitz.config.js');
module.exports = withBlitz(config);
module.exports = config;
`),
}),
)
@@ -74,10 +73,9 @@ module.exports = withBlitz(config);
})
file.contents = Buffer.from(`
const {withBlitz} = require('@blitzjs/core/with-blitz');
const vercelConfig = require('./next-vercel.config.js');
const config = require('../blitz.config.js');
module.exports = withBlitz({...config, ...vercelConfig});
module.exports = {...config, ...vercelConfig};
`)
}

View File

@@ -1,5 +1,5 @@
diff --git a/node_modules/@preconstruct/cli/cli/dist/cli.cjs.dev.js b/node_modules/@preconstruct/cli/cli/dist/cli.cjs.dev.js
index 972d57b..9215a89 100644
index 972d57b..a8d19eb 100644
--- a/node_modules/@preconstruct/cli/cli/dist/cli.cjs.dev.js
+++ b/node_modules/@preconstruct/cli/cli/dist/cli.cjs.dev.js
@@ -166,7 +166,7 @@ function format(args, messageType, scope) {
@@ -11,7 +11,17 @@ index 972d57b..9215a89 100644
return fullPrefix + util.format("", ...args).split("\n").reduce((str, line) => {
const prefixed = `${str}\n${fullPrefix}`;
return line ? `${prefixed} ${line}` : prefixed;
@@ -1917,6 +1917,8 @@ let getRollupConfig = (pkg, entrypoints, aliases, type, reportTransformedFile) =
@@ -847,6 +847,9 @@ const isFieldValid = {
},
browser(entrypoint) {
+ if (/packages[\\/]config/.test(entrypoint.directory)) {
+ return true
+ }
return equal(entrypoint.json.browser, validFields.browser(entrypoint));
}
@@ -1917,6 +1920,8 @@ let getRollupConfig = (pkg, entrypoints, aliases, type, reportTransformedFile) =
external.push(...builtInModules);
}
@@ -20,3 +30,14 @@ index 972d57b..9215a89 100644
let input = {};
entrypoints.forEach(entrypoint => {
input[path__default.relative(pkg.directory, path__default.join(entrypoint.directory, "dist", getNameForDistForEntrypoint(entrypoint)))] = entrypoint.source;
@@ -2129,6 +2134,10 @@ function getRollupConfigs(pkg, aliases) {
});
let hasBrowserField = pkg.entrypoints[0].json.browser !== undefined;
+ if (["@blitzjs/config"].includes(pkg.entrypoints[0].json.name)) {
+ hasBrowserField = false
+ }
+
if (hasBrowserField) {
configs.push({
config: getRollupConfig(pkg, pkg.entrypoints, aliases, "browser", () => {}),