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

feat(gatsby): ESM in gatsby-config.mjs and gatsby-node.mjs #37068

Merged
merged 37 commits into from Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
69cc5c9
feat(gatsby): ESM in gatsby-config.mjs proof of concept
tyhopp Nov 16, 2022
d8e7317
Explore gatsby-node.mjs support
tyhopp Nov 16, 2022
f773168
Make gatsby-node.mjs engines bundling work
tyhopp Nov 17, 2022
a98992d
Adjust resolve-module-exports to match require behavior
tyhopp Nov 17, 2022
4c32983
Make gatsby-config.js|.mjs|.ts work
tyhopp Nov 18, 2022
ddd8def
Merge branch 'master' into feat/esm-in-gatsby-files
LekoArts Nov 18, 2022
e0165a8
Revert changes to compile-gatsby-files
tyhopp Nov 21, 2022
7cae3ed
Use single codepath in get-config-file
tyhopp Nov 21, 2022
24998e0
Add basic integration test
tyhopp Nov 21, 2022
dcf2d63
Commit test fixtures
tyhopp Nov 22, 2022
7b2fd81
Integration test for gatsby-config.mjs in plugins
tyhopp Nov 22, 2022
1054085
Tell babel to only keep dynamic imports in files that need it
tyhopp Nov 22, 2022
e0cd66a
Integration test for gatsby-node.mjs
tyhopp Nov 22, 2022
ea03d6f
Integration test for gatsby-node.mjs bundled in engines
tyhopp Nov 22, 2022
fafbe19
Handle import errors
marvinjude Nov 22, 2022
7a75ac7
Adjust get-config-file test to make room for esm cases
tyhopp Nov 23, 2022
43f8676
Flatten get-config-file, make unit and integration tests pass
tyhopp Nov 23, 2022
f32ce8b
Add test for resolve-config-file-path util
tyhopp Nov 23, 2022
e6893bc
Use relative path in warning for resolve-config-file-path
tyhopp Nov 23, 2022
ed0a480
test(gatsby): Add esm-in-gatsby-files integration test to circleci co…
marvinjude Nov 29, 2022
fa72d4a
test(gatsby): test that ESM only rehype/remark plugins work in `gatsb…
marvinjude Nov 29, 2022
d9fd79f
test(gatsby): Make `resolveModuleExports` tests pass (#37105)
marvinjude Nov 29, 2022
926a1fe
Merge branch 'master' into feat/esm-in-gatsby-files
LekoArts Nov 29, 2022
e843c6f
test(gatsby): Adjust jest config, make get-config test pass in esm ca…
marvinjude Nov 29, 2022
b8d30be
Update jest.config.js
LekoArts Nov 29, 2022
3f13313
update jest config transform regex
marvinjude Nov 29, 2022
23e5c25
fix job/manager tests
pieh Nov 29, 2022
0998143
add babel-preset-gatsby-package to itest devDeps
marvinjude Nov 29, 2022
ed00873
fix collate plugin tests
marvinjude Nov 29, 2022
97f9710
feat(gatsby): Telemetry tracking for ESM (#37122)
marvinjude Nov 30, 2022
c999011
allow empty gatsby-config.mjs files
marvinjude Nov 30, 2022
b4e07e8
refactor(gatsby): gatsby-node.mjs cleanup (#37128)
tyhopp Dec 6, 2022
420c836
Fix api-runner-node fixtures
tyhopp Dec 6, 2022
b9dbdac
Fix jobs manager fixtures
tyhopp Dec 6, 2022
d86c031
Remove testRequireError, refactor tests
tyhopp Dec 8, 2022
ac899b3
DRY get-config-file error case in src dir
tyhopp Dec 8, 2022
f9f6c04
Do not copy unused test-require-error file during init
tyhopp Dec 8, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions .circleci/config.yml
Expand Up @@ -306,6 +306,13 @@ jobs:
test_path: integration-tests/head-function-export
test_command: yarn test

integration_tests_esm_in_gatsby_files:
executor: node
steps:
- e2e-test:
test_path: integration-tests/esm-in-gatsby-files
test_command: yarn test

e2e_tests_path-prefix:
<<: *e2e-executor
environment:
Expand Down Expand Up @@ -592,6 +599,8 @@ workflows:
<<: *e2e-test-workflow
- integration_tests_head_function_export:
<<: *e2e-test-workflow
- integration_tests_esm_in_gatsby_files:
<<: *e2e-test-workflow
- integration_tests_gatsby_cli:
requires:
- bootstrap
Expand Down
@@ -0,0 +1,15 @@
describe(`ESM only Rehype & Remark plugins`, () => {
describe("Remark Plugin", () => {
it(`transforms to github-like checkbox list`, () => {
cy.visit(`/using-esm-only-rehype-remark-plugins/`).waitForRouteChange()
cy.get(`.task-list-item`).should("have.length", 2)
})
})

describe("Rehype Plugin", () => {
it(`use heading text as id `, () => {
cy.visit(`/using-esm-only-rehype-remark-plugins/`).waitForRouteChange()
cy.get(`#heading-two`).invoke(`text`).should(`eq`, `Heading two`)
})
})
})
22 changes: 20 additions & 2 deletions e2e-tests/mdx/gatsby-config.js → e2e-tests/mdx/gatsby-config.mjs
@@ -1,4 +1,11 @@
module.exports = {
import remarkGfm from "remark-gfm"
import rehypeSlug from "rehype-slug"
import { dirname } from "path"
import { fileURLToPath } from "url"

const __dirname = dirname(fileURLToPath(import.meta.url))

const config = {
siteMetadata: {
title: `Gatsby MDX e2e`,
},
Expand Down Expand Up @@ -28,7 +35,16 @@ module.exports = {
`gatsby-remark-autolink-headers`,
],
mdxOptions: {
remarkPlugins: [remarkRequireFilePathPlugin],
remarkPlugins: [
remarkRequireFilePathPlugin,
// This is an esm only packages, It should work out of the box
remarkGfm,
],

rehypePlugins: [
// This is an esm only packages, It should work out of the box
rehypeSlug,
],
},
},
},
Expand All @@ -47,3 +63,5 @@ function remarkRequireFilePathPlugin() {
}
}
}

export default config
2 changes: 2 additions & 0 deletions e2e-tests/mdx/package.json
Expand Up @@ -16,6 +16,8 @@
"gatsby-source-filesystem": "next",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"theme-ui": "^0.3.1"
},
"keywords": [
Expand Down
@@ -0,0 +1,8 @@
---
title: Using esm only rehype & rehype plugins
---

## Heading two

- [ ] A
- [x] B
8 changes: 8 additions & 0 deletions integration-tests/esm-in-gatsby-files/.gitignore
@@ -0,0 +1,8 @@
__tests__/__debug__
node_modules
yarn.lock

# These are removed and created during the test lifecycle
./gatsby-config.js
./gatsby-config.mjs
./gatsby-config.ts
@@ -0,0 +1,13 @@
// This fixture is moved during the test lifecycle

const helloDefaultCJS = require(`./cjs-default.js`)
const { helloNamedCJS } = require(`./cjs-named.js`)

helloDefaultCJS()
helloNamedCJS()

const config = {
plugins: [],
}

module.exports = config
@@ -0,0 +1,21 @@
// This fixture is moved during the test lifecycle

import slugify from "@sindresorhus/slugify";
import helloDefaultESM from "./esm-default.mjs"
import { helloNamedESM } from "./esm-named.mjs"

helloDefaultESM()
helloNamedESM()

const config = {
plugins: [
{
resolve: `a-local-plugin`,
options: {
slugify,
},
},
],
}

export default config
@@ -0,0 +1,12 @@
const createResolvers = ({ createResolvers }) => {
createResolvers({
Query: {
fieldAddedByESMPlugin: {
type: `String`,
resolve: () => `gatsby-node-engine-bundled-mjs`
}
}
})
}

export { createResolvers }
@@ -0,0 +1,11 @@
// This fixture is moved during the test lifecycle

const helloDefaultCJS = require(`./cjs-default.js`)
const { helloNamedCJS } = require(`./cjs-named.js`)

helloDefaultCJS()
helloNamedCJS()

exports.onPreBuild = () => {
console.info(`gatsby-node-cjs-on-pre-build`);
};
@@ -0,0 +1,11 @@
// This fixture is moved during the test lifecycle

import helloDefaultESM from "./esm-default.mjs"
import { helloNamedESM } from "./esm-named.mjs"

helloDefaultESM()
helloNamedESM()

export const onPreBuild = () => {
console.info(`gatsby-node-esm-on-pre-build`);
};
@@ -0,0 +1,22 @@
import React from "react"
import { graphql } from "gatsby"

function SSRPage({ data, serverData }) {
return <pre>{JSON.stringify({ data, serverData }, null, 2)}</pre>
}

export const query = graphql`
{
fieldAddedByESMPlugin
}
`

export const getServerData = () => {
return {
props: {
ssr: true,
},
}
}

export default SSRPage
@@ -0,0 +1,9 @@
// This fixture is moved during the test lifecycle

console.info(`a-local-plugin-gatsby-config-mjs`)

const config = {
plugins: [],
}

export default config
@@ -0,0 +1,3 @@
export const onPreBuild = (_, { slugify }) => {
console.info(slugify(`a local plugin using passed esm module`));
};
@@ -0,0 +1 @@
// noop
@@ -0,0 +1,12 @@
{
"name": "a-local-plugin",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
@@ -0,0 +1,84 @@
import path from "path"
import fs from "fs-extra"
import execa from "execa"

jest.setTimeout(100000)

const fixtureRoot = path.resolve(__dirname, `fixtures`)
const siteRoot = path.resolve(__dirname, `..`)

const fixturePath = {
cjs: path.join(fixtureRoot, `gatsby-config.js`),
esm: path.join(fixtureRoot, `gatsby-config.mjs`),
}

const configPath = {
cjs: path.join(siteRoot, `gatsby-config.js`),
esm: path.join(siteRoot, `gatsby-config.mjs`),
}

const localPluginFixtureDir = path.join(fixtureRoot, `plugins`)
const localPluginTargetDir = path.join(siteRoot, `plugins`)

const gatsbyBin = path.join(`node_modules`, `gatsby`, `cli.js`)

async function build() {
const { stdout } = await execa(process.execPath, [gatsbyBin, `build`], {
env: {
...process.env,
NODE_ENV: `production`,
},
})

return stdout
}

// Tests include multiple assertions since running multiple builds is time consuming

describe(`gatsby-config.js`, () => {
afterEach(() => {
fs.rmSync(configPath.cjs)
})

it(`works with required CJS modules`, async () => {
await fs.copyFile(fixturePath.cjs, configPath.cjs)

const stdout = await build()

// Build succeeded
expect(stdout).toContain(`Done building`)

// Requires work
expect(stdout).toContain(`hello-default-cjs`)
expect(stdout).toContain(`hello-named-cjs`)
})
})

describe(`gatsby-config.mjs`, () => {
afterEach(async () => {
await fs.rm(configPath.esm)
await fs.rm(localPluginTargetDir, { recursive: true })
})

it(`works with imported ESM modules`, async () => {
await fs.copyFile(fixturePath.esm, configPath.esm)

await fs.ensureDir(localPluginTargetDir)
await fs.copy(localPluginFixtureDir, localPluginTargetDir)

const stdout = await build()

// Build succeeded
expect(stdout).toContain(`Done building`)

// Imports work
expect(stdout).toContain(`hello-default-esm`)
expect(stdout).toContain(`hello-named-esm`)

// Local plugin gatsby-config.mjs works
expect(stdout).toContain(`a-local-plugin-gatsby-config-mjs`)

// Local plugin with an esm module passed via options works, this implicitly tests gatsby-node.mjs too
expect(stdout).toContain(`a-local-plugin-using-passed-esm-module`)
})
})