Compare commits
27 Commits
react18
...
support-bl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf92448359 | ||
|
|
d4bfa153fb | ||
|
|
203c24cf11 | ||
|
|
3b15f360bf | ||
|
|
9f96c0712b | ||
|
|
38ed5609c1 | ||
|
|
6b8e2c7f22 | ||
|
|
714db4893b | ||
|
|
5126214a17 | ||
|
|
9df8448d64 | ||
|
|
437d3379f4 | ||
|
|
411c321b90 | ||
|
|
b3b053575c | ||
|
|
da87679f84 | ||
|
|
026f104f51 | ||
|
|
3d9d021802 | ||
|
|
fe9ced9bab | ||
|
|
a6a09d6980 | ||
|
|
5572c9c323 | ||
|
|
c5435fd741 | ||
|
|
4c05972707 | ||
|
|
fa7bb69ff8 | ||
|
|
c08dc7d832 | ||
|
|
6221782cc9 | ||
|
|
712e658e4b | ||
|
|
fbc9b88631 | ||
|
|
20314c37c4 |
@@ -442,6 +442,7 @@ Thanks to these wonderful people ([emoji key](https://allcontributors.org/docs/e
|
||||
|
||||
<!-- markdownlint-enable -->
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const {sessionMiddleware, unstable_simpleRolesIsAuthorized} = require("@blitzjs/server")
|
||||
const withBundleAnalyzer = require("@next/bundle-analyzer")({
|
||||
import {sessionMiddleware, unstable_simpleRolesIsAuthorized} from "@blitzjs/server"
|
||||
import bundleAnalyzer from "@next/bundle-analyzer"
|
||||
|
||||
const withBundleAnalyzer = bundleAnalyzer({
|
||||
enabled: process.env.ANALYZE === "true",
|
||||
})
|
||||
|
||||
module.exports = withBundleAnalyzer({
|
||||
export default withBundleAnalyzer({
|
||||
middleware: [
|
||||
sessionMiddleware({
|
||||
unstable_isAuthorized: unstable_simpleRolesIsAuthorized,
|
||||
@@ -16,6 +16,6 @@
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"exclude": ["node_modules", "**/*.test.tsx"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
"@types/mem-fs": "1.1.2",
|
||||
"@types/mem-fs-editor": "5.1.1",
|
||||
"@types/merge-stream": "1.1.2",
|
||||
"@types/mock-fs": "4.10.0",
|
||||
"@types/mock-fs": "4.13.0",
|
||||
"@types/node": "13.13.2",
|
||||
"@types/node-fetch": "2.5.7",
|
||||
"@types/parallel-transform": "1.1.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import {PHASE_DEVELOPMENT_SERVER, PHASE_PRODUCTION_SERVER} from "next/constants"
|
||||
import {join} from "path"
|
||||
import pkgDir from "pkg-dir"
|
||||
|
||||
const configFiles = ["blitz.config.js", "next.config.js"]
|
||||
const configFiles = ["blitz.config.js", ".next/blitz.config.js", "next.config.js"]
|
||||
/**
|
||||
* @param {boolean | undefined} reload - reimport config files to reset global cache
|
||||
*/
|
||||
@@ -18,7 +18,9 @@ export const getConfig = (reload?: boolean): Record<string, unknown> => {
|
||||
for (const configFile of configFiles) {
|
||||
if (existsSync(join(projectRoot, configFile))) {
|
||||
const path = join(projectRoot, configFile)
|
||||
const file = require(path)
|
||||
let file = require(path)
|
||||
file = file.default ?? file
|
||||
|
||||
let contents
|
||||
if (typeof file === "function") {
|
||||
const phase =
|
||||
@@ -27,6 +29,7 @@ export const getConfig = (reload?: boolean): Record<string, unknown> => {
|
||||
} else {
|
||||
contents = file
|
||||
}
|
||||
|
||||
blitzConfig = {
|
||||
...blitzConfig,
|
||||
...contents,
|
||||
|
||||
@@ -3,3 +3,4 @@ export {Stage, PipelineItem} from "./types"
|
||||
export * from "./events"
|
||||
export {transform} from "./transform"
|
||||
export {FileCache} from "./helpers/file-cache"
|
||||
export * from "./streams"
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"@blitzjs/config": "0.25.0",
|
||||
"@blitzjs/display": "0.25.0",
|
||||
"@blitzjs/file-pipeline": "0.25.0",
|
||||
"@vercel/ncc": "0.25.1",
|
||||
"b64-lite": "1.4.0",
|
||||
"cookie": "0.4.1",
|
||||
"cross-spawn": "7.0.3",
|
||||
@@ -69,6 +70,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@blitzjs/core": "0.25.0",
|
||||
"@blitzjs/file-pipeline": "0.25.0",
|
||||
"next-transpile-modules": "3.2.0"
|
||||
},
|
||||
"gitHead": "d3b9fce0bdd251c2b1890793b0aa1cd77c1c0922"
|
||||
|
||||
@@ -43,6 +43,13 @@ export async function build(
|
||||
}
|
||||
|
||||
if (await pathExists(buildNextFolder)) {
|
||||
// Ensure the `blitz.config.js` file is copied over
|
||||
const blitzConfig = resolve(buildFolder, "blitz.config.js")
|
||||
if (await pathExists(blitzConfig)) {
|
||||
const blitzConfigDest = resolve(buildNextFolder, "blitz.config.js")
|
||||
await copy(blitzConfig, blitzConfigDest)
|
||||
}
|
||||
|
||||
await copy(buildNextFolder, rootNextFolder)
|
||||
}
|
||||
|
||||
|
||||
99
packages/server/src/ncc.d.ts
vendored
Normal file
99
packages/server/src/ncc.d.ts
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// From https://gist.github.com/cinderblock/e25cc7ddc201625fd00449a27c8fe0bf
|
||||
declare module "@vercel/ncc" {
|
||||
/**
|
||||
* Options except watch.
|
||||
*/
|
||||
type Options = {
|
||||
/**
|
||||
* Provide a custom cache path or disable caching.
|
||||
*/
|
||||
cache?: string | false
|
||||
|
||||
/**
|
||||
* Externals to leave as requires of the build.
|
||||
*/
|
||||
externals?: string[]
|
||||
|
||||
/**
|
||||
* Directory outside of which never to emit assets.
|
||||
*
|
||||
* @default process.cwd()
|
||||
*/
|
||||
filterAssetBase?: string
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
minify?: boolean
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
sourceMap?: boolean
|
||||
|
||||
/**
|
||||
* Default treats sources as output-relative.
|
||||
*
|
||||
* @default '../'
|
||||
*/
|
||||
sourceMapBasePrefix?: string
|
||||
|
||||
/**
|
||||
* When outputting a sourcemap, automatically include
|
||||
* source-map-support in the output file (increases output by 32kB).
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
sourceMapRegister?: boolean
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
v8cache?: boolean
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
quiet?: boolean
|
||||
|
||||
/**
|
||||
* @default false
|
||||
*/
|
||||
debugLog?: boolean
|
||||
}
|
||||
|
||||
type Assets = {
|
||||
[filename: string]: {
|
||||
source: Buffer
|
||||
permissions: number
|
||||
symlinks: unknown // TODO: fix type
|
||||
}
|
||||
}
|
||||
|
||||
type Result = {code: string; map: string; assets: Assets}
|
||||
|
||||
function ncc(input: string, options: Options & {watch?: false}): Promise<Result>
|
||||
|
||||
function ncc(
|
||||
input: string,
|
||||
options: Options & {watch: true},
|
||||
): {
|
||||
/**
|
||||
* Handler re-run on each build completion
|
||||
* watch errors are reported on "err".
|
||||
*/
|
||||
handler(data: {err: Error} | Result): void
|
||||
|
||||
/**
|
||||
* Handler re-run on each rebuild start.
|
||||
*/
|
||||
rebuild(): void
|
||||
|
||||
/**
|
||||
* Close the watcher.
|
||||
*/
|
||||
close(): void
|
||||
}
|
||||
|
||||
export = ncc
|
||||
}
|
||||
@@ -1,11 +1,20 @@
|
||||
import {transform} from "@blitzjs/file-pipeline"
|
||||
import {Stage} from "@blitzjs/file-pipeline"
|
||||
import bundle from "@vercel/ncc"
|
||||
import {pathExistsSync} from "fs-extra"
|
||||
import {resolve} from "path"
|
||||
import File from "vinyl"
|
||||
|
||||
const isNextConfigPath = (p: string) => /next\.config\.(js|ts)/.test(p)
|
||||
const isBlitzTsConfigPath = (p: string) => /blitz\.config\.ts/.test(p)
|
||||
const isNowBuild = () => process.env.NOW_BUILDER || process.env.VERCEL_BUILDER
|
||||
|
||||
const nextConfigSupportError = (msg: string): Error => {
|
||||
const err = new Error(msg)
|
||||
err.name = "NextConfigSupportError"
|
||||
return err
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Stage that manages converting from blitz.config.js to next.config.js
|
||||
*/
|
||||
@@ -13,17 +22,22 @@ export const createStageConfig: Stage = ({config, processNewFile, processNewChil
|
||||
// Preconditions
|
||||
const hasNextConfig = pathExistsSync(resolve(config.src, "next.config.js"))
|
||||
const hasBlitzConfig = pathExistsSync(resolve(config.src, "blitz.config.js"))
|
||||
const hasBlitzTsConfig = pathExistsSync(resolve(config.src, "blitz.config.ts"))
|
||||
|
||||
if (hasNextConfig && !isNowBuild()) {
|
||||
// TODO: Pause the stream and ask the user if they wish to have their configuration file renamed
|
||||
const err = new Error(
|
||||
throw nextConfigSupportError(
|
||||
"Blitz does not support next.config.js. Please rename your next.config.js to blitz.config.js",
|
||||
)
|
||||
err.name = "NextConfigSupportError"
|
||||
throw err
|
||||
}
|
||||
|
||||
if (!hasBlitzConfig) {
|
||||
if (hasBlitzConfig && hasBlitzTsConfig) {
|
||||
throw nextConfigSupportError(
|
||||
"Blitz has found blitz.config.js and blitz.config.ts. Please delete one of these configuration files.",
|
||||
)
|
||||
}
|
||||
|
||||
if (!hasBlitzConfig && !hasBlitzTsConfig) {
|
||||
// Assume a bare blitz config
|
||||
processNewFile(
|
||||
new File({
|
||||
@@ -42,14 +56,26 @@ export const createStageConfig: Stage = ({config, processNewFile, processNewChil
|
||||
contents: Buffer.from(`
|
||||
const {withBlitz} = require('@blitzjs/server');
|
||||
const config = require('./blitz.config.js');
|
||||
module.exports = withBlitz(config);
|
||||
module.exports = withBlitz(config.default ? config.default : config);
|
||||
`),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
// No need to filter yet
|
||||
const stream = transform.file((file) => {
|
||||
const stream = transform.file(async (file) => {
|
||||
if (isBlitzTsConfigPath(file.path)) {
|
||||
const res = await bundle(file.path, {
|
||||
quiet: true,
|
||||
externals: ["@blitzjs/server", "@next/bundle-analyzer"], // FIXME: Figure out why this wouldn't work? Do we need to bundle everything?
|
||||
})
|
||||
|
||||
file.path = resolve(config.src, "blitz.config.js")
|
||||
file.contents = Buffer.from(res.code)
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
if (!isNextConfigPath(file.path)) return file
|
||||
|
||||
// File is next.config.js
|
||||
@@ -75,7 +101,7 @@ module.exports = withBlitz(config);
|
||||
const {withBlitz} = require('@blitzjs/server');
|
||||
const vercelConfig = require('./next-vercel.config.js');
|
||||
const config = require('./blitz.config.js');
|
||||
module.exports = withBlitz({...config, ...vercelConfig});
|
||||
module.exports = withBlitz({...(config.default ? config.default : config), ...vercelConfig});
|
||||
`)
|
||||
}
|
||||
|
||||
|
||||
122
packages/server/test/stages/config.test.ts
Normal file
122
packages/server/test/stages/config.test.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import {through, transformFiles} from "@blitzjs/file-pipeline"
|
||||
import path from "path"
|
||||
import {createStageConfig} from "../../src/stages/config"
|
||||
import {mockFs} from "../utils/multi-mock"
|
||||
import {directoryTree} from "../utils/tree-utils"
|
||||
|
||||
describe("config stage", () => {
|
||||
const processNewFile = () => {}
|
||||
const processNewChildFile = () => {}
|
||||
const getInputCache = jest.fn()
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
mockFs.restore()
|
||||
})
|
||||
|
||||
it("throws an error when `next.config.js` exists", () => {
|
||||
mockFs({
|
||||
"src/next.config.js": "",
|
||||
})
|
||||
|
||||
const input = through.obj()
|
||||
const bus = through.obj()
|
||||
|
||||
expect(() => {
|
||||
createStageConfig({
|
||||
config: {
|
||||
src: "src",
|
||||
cwd: "src",
|
||||
dest: "dest",
|
||||
include: [],
|
||||
ignore: [],
|
||||
watch: false,
|
||||
},
|
||||
processNewFile,
|
||||
processNewChildFile,
|
||||
input,
|
||||
bus,
|
||||
getInputCache,
|
||||
})
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Blitz does not support next.config.js. Please rename your next.config.js to blitz.config.js"`,
|
||||
)
|
||||
})
|
||||
|
||||
it("throws an error when `blitz.config.js` and `blitz.config.ts` both exist", () => {
|
||||
mockFs({
|
||||
"src/blitz.config.js": "",
|
||||
"src/blitz.config.ts": "",
|
||||
})
|
||||
|
||||
const input = through.obj()
|
||||
const bus = through.obj()
|
||||
|
||||
expect(() => {
|
||||
createStageConfig({
|
||||
config: {
|
||||
src: "src",
|
||||
cwd: "src",
|
||||
dest: "dest",
|
||||
include: [],
|
||||
ignore: [],
|
||||
watch: false,
|
||||
},
|
||||
processNewFile,
|
||||
processNewChildFile,
|
||||
input,
|
||||
bus,
|
||||
getInputCache,
|
||||
})
|
||||
}).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Blitz has found blitz.config.js and blitz.config.ts. Please delete one of these configuration files."`,
|
||||
)
|
||||
})
|
||||
|
||||
it("transpiles the `blitz.config.ts` file", async () => {
|
||||
const nodeModulesDir = path.resolve(__dirname, "../../../../node_modules")
|
||||
|
||||
mockFs({
|
||||
"src/blitz.config.ts": `export default {}`,
|
||||
"src/tsconfig.json": `{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "esnext",
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
|
||||
}`,
|
||||
[nodeModulesDir]: mockFs.load(nodeModulesDir),
|
||||
})
|
||||
|
||||
const options = {
|
||||
watch: false,
|
||||
ignore: [],
|
||||
include: ["**/*"],
|
||||
}
|
||||
await transformFiles("src", [createStageConfig], "dest", options)
|
||||
|
||||
expect(directoryTree("dest")).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"children": Array [
|
||||
Object {
|
||||
"name": ".blitz.incache.json",
|
||||
},
|
||||
Object {
|
||||
"name": "blitz.config.js",
|
||||
},
|
||||
Object {
|
||||
"name": "next.config.js",
|
||||
},
|
||||
Object {
|
||||
"name": "tsconfig.json",
|
||||
},
|
||||
],
|
||||
"name": "dest",
|
||||
}
|
||||
`)
|
||||
}, 20000)
|
||||
})
|
||||
@@ -1,6 +1,6 @@
|
||||
import mockFileSystem from "mock-fs"
|
||||
|
||||
const mockFs = (...args: any[]) => {
|
||||
export const mockFs = (...args: any[]) => {
|
||||
// Fixes an issue with mockFs around console log in tests and dependencies
|
||||
// This is a magic workaround until mock-fs provides an overlay functionality
|
||||
// Tried using union fs and memfs but it wasn't working properly
|
||||
@@ -11,6 +11,7 @@ const mockFs = (...args: any[]) => {
|
||||
|
||||
// We may need to add more methods here if we need them
|
||||
mockFs.restore = mockFileSystem.restore
|
||||
mockFs.load = mockFileSystem.load
|
||||
|
||||
/**
|
||||
* Mock multiple dependencies at once for a test. Returns a mock
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { addImport, paths, RecipeBuilder } from "@blitzjs/installer"
|
||||
import { NodePath } from "ast-types/lib/node-path"
|
||||
import {addImport, paths, RecipeBuilder} from "@blitzjs/installer"
|
||||
import {NodePath} from "ast-types/lib/node-path"
|
||||
import j from "jscodeshift"
|
||||
import { Collection } from "jscodeshift/src/Collection"
|
||||
import {Collection} from "jscodeshift/src/Collection"
|
||||
|
||||
// Copied from https://github.com/blitz-js/blitz/pull/805, let's add this to the @blitzjs/installer
|
||||
function wrapComponentWithChakraProvider(program: Collection<j.Program>) {
|
||||
@@ -13,16 +13,12 @@ function wrapComponentWithChakraProvider(program: Collection<j.Program>) {
|
||||
path.parent?.value.type === j.ReturnStatement.toString(),
|
||||
)
|
||||
.forEach((path: NodePath) => {
|
||||
const { node } = path
|
||||
const {node} = path
|
||||
path.replace(
|
||||
j.jsxElement(
|
||||
j.jsxOpeningElement(j.jsxIdentifier("ChakraProvider")),
|
||||
j.jsxClosingElement(j.jsxIdentifier("ChakraProvider")),
|
||||
[
|
||||
j.jsxText("\n"),
|
||||
node,
|
||||
j.jsxText("\n"),
|
||||
],
|
||||
[j.jsxText("\n"), node, j.jsxText("\n")],
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -41,10 +37,10 @@ export default RecipeBuilder()
|
||||
stepName: "Add npm dependencies",
|
||||
explanation: `Chakra requires some other dependencies like emotion to work`,
|
||||
packages: [
|
||||
{ name: "@chakra-ui/react", version: "latest" },
|
||||
{ name: "@emotion/react", version: "latest" },
|
||||
{ name: "@emotion/styled", version: "latest" },
|
||||
{ name: "framer-motion", version: "latest" },
|
||||
{name: "@chakra-ui/react", version: "latest"},
|
||||
{name: "@emotion/react", version: "latest"},
|
||||
{name: "@emotion/styled", version: "latest"},
|
||||
{name: "framer-motion", version: "latest"},
|
||||
],
|
||||
})
|
||||
.addTransformFilesStep({
|
||||
|
||||
13
yarn.lock
13
yarn.lock
@@ -4293,10 +4293,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-7.0.2.tgz#b17f16cf933597e10d6d78eae3251e692ce8b0ce"
|
||||
integrity sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==
|
||||
|
||||
"@types/mock-fs@4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/mock-fs/-/mock-fs-4.10.0.tgz#460061b186993d76856f669d5317cda8a007c24b"
|
||||
integrity sha512-FQ5alSzmHMmliqcL36JqIA4Yyn9jyJKvRSGV3mvPh108VFatX7naJDzSG4fnFQNZFq9dIx0Dzoe6ddflMB2Xkg==
|
||||
"@types/mock-fs@4.13.0":
|
||||
version "4.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/mock-fs/-/mock-fs-4.13.0.tgz#b8b01cd2db588668b2532ecd21b1babd3fffb2c0"
|
||||
integrity sha512-FUqxhURwqFtFBCuUj3uQMp7rPSQs//b3O9XecAVxhqS9y4/W8SIJEZFq2mmpnFVZBXwR/2OyPLE97CpyYiB8Mw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
@@ -4890,6 +4890,11 @@
|
||||
"@typescript-eslint/types" "4.3.1-alpha.1+d72951ac"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
"@vercel/ncc@0.25.1":
|
||||
version "0.25.1"
|
||||
resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.25.1.tgz#a4aacdb508ac496fc0c63a3c3203d700a619cc0e"
|
||||
integrity sha512-dGecC5+1wLof1MQpey4+6i2KZv4Sfs6WfXkl9KfO32GED4ZPiKxRfvtGPjbjZv0IbqMl6CxtcV1RotXYfd5SSA==
|
||||
|
||||
"@webassemblyjs/ast@1.9.0":
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964"
|
||||
|
||||
Reference in New Issue
Block a user