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

Convert @redwoodjs/web to ESM/CJS dual package #10868

Merged
merged 73 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
4e003b1
Convert tsc bin to mts
dac09 Jun 7, 2024
794466b
Add build.mts
dac09 Jun 7, 2024
169d622
Update build script for rwjs/web
dac09 Jun 7, 2024
669c595
Update buildDefaults in framework tools to include .mts
dac09 Jun 7, 2024
bf128bb
Restore tsc bin to how it was to check CJS build first
dac09 Jun 7, 2024
db802ad
Add react imports to everything that has JSX
dac09 Jun 7, 2024
40b4b7b
Remove React from eslint auto import rule
dac09 Jun 7, 2024
209cbe6
Fix linting errors caused by eslint rule removal
dac09 Jun 7, 2024
88877ca
Update build.mts with comments
dac09 Jun 7, 2024
d853319
Merge branch 'main' of github.com:redwoodjs/redwood into chore/web-pa…
dac09 Jun 17, 2024
5c2e4f9
Update comments
dac09 Jun 17, 2024
58e08c7
Bump tsx version
dac09 Jun 17, 2024
92d4d31
Handle webpack entrry
dac09 Jun 17, 2024
8561805
Add react to webpack entry
dac09 Jun 17, 2024
1cbc42d
Merge branch 'main' into chore/web-package-cjsonly-new-build
dac09 Jun 17, 2024
c6eb4a7
export default for bundle removal
dac09 Jun 18, 2024
517fed0
Merge branch 'main' into chore/web-package-cjsonly-new-build
dac09 Jun 18, 2024
ea1be4c
Just do export default
dac09 Jun 18, 2024
2db4ec9
Merge branch 'main' into chore/web-package-cjsonly-new-build
dac09 Jun 19, 2024
5e43bde
Update yarn.lock
dac09 Jun 19, 2024
f8c34e2
Bump tsx version to match other packages
dac09 Jun 19, 2024
ccf9954
Set exports and type module
dac09 Jun 19, 2024
517208e
Add extensions to all relative imports in packages/web
dac09 Jun 19, 2024
f451c30
Remove module augmentation syntax for asset imports as not supported …
dac09 Jun 19, 2024
f8b6edb
cjsInterop - update settings to not transform auth or web. Why was au…
dac09 Jun 20, 2024
152cd80
Remove babel from vitest config
dac09 Jun 20, 2024
619d8d5
Add export "type" for cell types
dac09 Jun 20, 2024
301fb0d
Fix apollo client imports for esm
dac09 Jun 20, 2024
9a1cba3
Type ovverride imports
dac09 Jun 20, 2024
8ebc02f
Remove extension from serverInject because exported
dac09 Jun 20, 2024
a8ae316
Fix graphql import for prerender
dac09 Jun 20, 2024
a20357f
ESM compatbility imports for react-helmet-async
dac09 Jun 21, 2024
80487d3
Use import * for helmet
dac09 Jun 21, 2024
78f3f78
Add useClient to apollo/suspense.tsx to prevent bundling
dac09 Jun 21, 2024
e756770
Fix streamInjector imports for rsc
dac09 Jun 21, 2024
42899f8
Fix apollo provider import in legacy dev with exports field
dac09 Jun 21, 2024
7a10a67
Update how sseLInk is imported to fix legacy builds
dac09 Jun 21, 2024
eb8ef72
Update path for apollo import proxy
dac09 Jun 21, 2024
a1d9015
Merge branch 'main' into chore/p2-web-esm
dac09 Jun 21, 2024
ae872d5
Fix fatal error boundary double default
dac09 Jun 24, 2024
02f9275
Use await import
dac09 Jun 24, 2024
360645c
Force cjs import of certain apollo deps
dac09 Jun 24, 2024
0459c6c
Merge branch 'main' of github.com:redwoodjs/redwood into chore/p2-web…
dac09 Jun 24, 2024
15876ac
Update test path
dac09 Jun 24, 2024
ae30ea6
Ignore type tests and avoid default import of gql tag
dac09 Jun 24, 2024
78ed8fd
Add entry export field
dac09 Jun 24, 2024
ee48b97
Undo ServerINject change
dac09 Jun 24, 2024
de2c3c2
Fix CJS issues with webpack
dac09 Jun 24, 2024
2e71a85
Use ESM version of webpack entry
dac09 Jun 24, 2024
aacb89a
Use serverInject from exports
dac09 Jun 24, 2024
37186b2
Temporarily remove buffer from devFatalError page
dac09 Jun 24, 2024
3a735ba
Update prerender import
dac09 Jun 24, 2024
5f03763
Remove serverStore, middleware exports fields. Not there yet!
dac09 Jun 24, 2024
b8cb183
Add tsconfig for building cjs types --- unsure
dac09 Jun 24, 2024
c32ce6b
Update comment
dac09 Jun 24, 2024
75d53ba
Disable helmet completely for SSR and RSC
dac09 Jun 24, 2024
b82fc37
Map jest preset to CJS build
dac09 Jun 24, 2024
ddd33b0
Reorder require and import
dac09 Jun 24, 2024
a8fc727
Cleanup build.mts
dac09 Jun 24, 2024
0a8628f
Make red squigglies go away on ssr project
dac09 Jun 24, 2024
9d4a794
Merge branch 'main' into chore/p2-web-esm
dac09 Jun 25, 2024
96a8d40
Merge branch 'chore/p2-web-esm' of github.com:dac09/redwood into chor…
dac09 Jun 26, 2024
9b4118a
Update apollo imports to make storybook-webpack work
dac09 Jun 26, 2024
028d2e7
Alias rwjs/web/apollo in storybook-webpack
dac09 Jun 27, 2024
12ce12d
Merge branch 'main' into chore/p2-web-esm
dac09 Jun 27, 2024
af27666
Add buffer polyfill for vite dev only for DevFatalErrorPage
dac09 Jun 27, 2024
e679f12
Update cjsInterop comments
dac09 Jun 27, 2024
9c210bf
Use vite client imports
dac09 Jun 27, 2024
d95c496
Merge branch 'main' of github.com:redwoodjs/redwood into chore/p2-web…
dac09 Jun 28, 2024
35a8deb
Import dts file specifically
dac09 Jun 28, 2024
9d06bc4
Move vite assets directive to typegen
dac09 Jun 28, 2024
0313271
Dont polyfill for rsc builds
dac09 Jun 28, 2024
c1ebecf
Merge branch 'main' into chore/p2-web-esm
dac09 Jun 28, 2024
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
2 changes: 1 addition & 1 deletion packages/core/config/webpack.common.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ module.exports = (webpackEnv) => {
*/
app:
redwoodPaths.web.index ||
require.resolve('@redwoodjs/web/dist/entry/index.js'),
require.resolve('@redwoodjs/web/webpackEntry'),
},
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.jsx', '.ts', '.tsx', '.json'],
Expand Down
17 changes: 17 additions & 0 deletions packages/internal/src/generate/typeDefinitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export const generateTypeDefs = async () => {
...generateTypeDefScenarios(),
...generateTypeDefTestMocks(),
...generateStubStorybookTypes(),
...generateViteClientTypesDirective(),
...gqlApiTypeDefFiles,
...gqlWebTypeDefFiles,
],
Expand Down Expand Up @@ -378,6 +379,22 @@ export const generateTypeDefGlobImports = () => {
export const generateTypeDefGlobalContext = () => {
return writeTypeDefIncludeFile('api-globalContext.d.ts.template')
}
/**
* Typescript does not preserve triple slash directives when outputting js or d.ts files.
* This is a work around so that *.svg, *.png, etc. imports have types.
*/
export const generateViteClientTypesDirective = () => {
const viteClientDirective = `/// <reference types="vite/client" />`
const redwoodProjectPaths = getPaths()

const viteClientDirectivePath = path.join(
redwoodProjectPaths.generated.types.includes,
'web-vite-client.d.ts',
)
fs.writeFileSync(viteClientDirectivePath, viteClientDirective)

return [viteClientDirectivePath]
}

function generateStubStorybookTypes() {
const stubStorybookTypesFileContent = `\
Expand Down
2 changes: 1 addition & 1 deletion packages/prerender/src/graphql/graphql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { print } from 'graphql'

import { getConfig, getPaths } from '@redwoodjs/project-config'
// @MARK: have to do this, otherwise rwjs/web is loaded before shims
import { getOperationName } from '@redwoodjs/web/dist/graphql'
import { getOperationName } from '@redwoodjs/web/dist/graphql.js'

import { GqlHandlerImportError } from '../errors'

Expand Down
2 changes: 1 addition & 1 deletion packages/testing/config/jest/web/jest-preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.exports = {
NODE_MODULES_PATH,
'@redwoodjs/testing/dist/web/MockRouter.js',
),
'^@redwoodjs/web$': path.join(NODE_MODULES_PATH, '@redwoodjs/web'),
'^@redwoodjs/web$': path.join(NODE_MODULES_PATH, '@redwoodjs/web/dist/cjs'),

// This allows us to mock `createAuthentication` which is used by auth
// clients, which in turn lets us mock `useAuth` in tests
Expand Down
8 changes: 8 additions & 0 deletions packages/testing/config/storybook/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ const baseConfig = {
sbConfig.resolve.alias['@redwoodjs/auth$'] = require.resolve(
'@redwoodjs/testing/dist/web/mockAuth.js',
)

// Force loading the ESM version of ApolloProvider in Storybook
// I'm unsure why storybook-webpack does not work with the CJS version
// All other cases are fine with the CJS import.
sbConfig.resolve.alias['@redwoodjs/web/apollo$'] = require.resolve(
'@redwoodjs/web/forceEsmApollo',
)

sbConfig.resolve.alias['~__REDWOOD__USER_ROUTES_FOR_MOCK'] =
redwoodProjectPaths.web.routes
sbConfig.resolve.alias['~__REDWOOD__USER_WEB_SRC'] =
Expand Down
1 change: 1 addition & 0 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"react-server-dom-webpack": "19.0.0-beta-04b058868c-20240508",
"vite": "5.3.1",
"vite-plugin-cjs-interop": "2.1.1",
"vite-plugin-node-polyfills": "^0.22.0",
"yargs-parser": "21.1.1"
},
"devDependencies": {
Expand Down
8 changes: 7 additions & 1 deletion packages/vite/src/devFeServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,13 @@ async function createServer() {
configFile: rwPaths.web.viteConfig,
plugins: [
cjsInterop({
dependencies: ['@redwoodjs/**'],
dependencies: [
// Skip ESM modules: rwjs/auth, rwjs/web
'@redwoodjs/forms',
'@redwoodjs/prerender/*',
'@redwoodjs/router',
'@redwoodjs/auth-*',
],
}),
rscEnabled && rscRoutesAutoLoader(),
],
Expand Down
12 changes: 12 additions & 0 deletions packages/vite/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import path from 'path'
import react from '@vitejs/plugin-react'
import type { PluginOption } from 'vite'
import { normalizePath } from 'vite'
import { nodePolyfills } from 'vite-plugin-node-polyfills'

import { getWebSideDefaultBabelConfig } from '@redwoodjs/babel-config'
import { getConfig, getPaths } from '@redwoodjs/project-config'
Expand Down Expand Up @@ -156,5 +157,16 @@ export default function redwoodPluginVite(): PluginOption[] {
}),
},
}),
// Only include the Buffer polyfill for non-rsc dev, for DevFatalErrorPage
// Including the polyfill plugin in any form in RSC breaks
!rscEnabled && {
...nodePolyfills({
include: ['buffer'],
globals: {
Buffer: true,
},
}),
apply: 'serve',
},
]
}
14 changes: 12 additions & 2 deletions packages/vite/src/rsc/rscBuildForSsr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,16 @@ export async function rscBuildForSsr({
],
},
plugins: [
cjsInterop({ dependencies: ['@redwoodjs/**'] }),
cjsInterop({
dependencies: [
// Skip ESM modules: rwjs/auth, rwjs/web
'@redwoodjs/forms',
'@redwoodjs/prerender/*',
'@redwoodjs/router',
'@redwoodjs/router/*',
'@redwoodjs/auth-*',
],
}),
rscRoutesAutoLoader(),
rscSsrRouterImport(),
],
Expand All @@ -84,10 +93,11 @@ export async function rscBuildForSsr({
// for the client-only components. They get loaded once the page is
// rendered
...clientEntryFiles,
// These import redirections are so that we don't bundle multiple versions of react
__rwjs__react: 'react',
__rwjs__location: '@redwoodjs/router/dist/location',
__rwjs__server_auth_provider: '@redwoodjs/auth/ServerAuthProvider',
__rwjs__server_inject: '@redwoodjs/web/dist/components/ServerInject',
__rwjs__server_inject: '@redwoodjs/web/serverInject',
'__rwjs__rsdw-client': 'react-server-dom-webpack/client.edge',
// TODO (RSC): add __rwjs__ prefix to the entry below
'rd-server': 'react-dom/server.edge',
Expand Down
8 changes: 7 additions & 1 deletion packages/vite/src/streaming/buildForStreamingServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ export async function buildForStreamingServer({
configFile: rwPaths.web.viteConfig,
plugins: [
cjsInterop({
dependencies: ['@redwoodjs/**'],
dependencies: [
// Skip ESM modules: rwjs/auth, rwjs/web
'@redwoodjs/forms',
'@redwoodjs/prerender/*',
'@redwoodjs/router',
'@redwoodjs/auth-*',
],
}),
],
build: {
Expand Down
8 changes: 6 additions & 2 deletions packages/vite/src/streaming/streamHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,16 @@ export async function reactRenderToStreamResponse(
const { createElement }: React = rscEnabled
? await importModule('__rwjs__react')
: await import('react')

const {
createInjector,
ServerHtmlProvider,
ServerInjectedHtml,
}: ServerInjectType = rscEnabled
? await importModule('__rwjs__server_inject')
: await import('@redwoodjs/web/dist/components/ServerInject.js')
: // @ts-expect-error this is defined in packages/web/package.json exports.
// This package just doesn't have moduleResolution configured
await import('@redwoodjs/web/serverInject')
const { renderToString }: RDServerType = rscEnabled
? await importModule('rd-server')
: await import('react-dom/server')
Expand Down Expand Up @@ -322,7 +325,8 @@ export async function importModule(
} else if (mod === '__rwjs__server_auth_provider') {
return await import(ServerAuthProviderPath)
} else if (mod === '__rwjs__server_inject') {
return (await import(ServerInjectPath)).default
// Don't need default because rwjs/web is now ESM
return await import(ServerInjectPath)
}

throw new Error('Unknown module ' + mod)
Expand Down
2 changes: 1 addition & 1 deletion packages/web/apollo/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
/* eslint-env es6, commonjs */
module.exports = require('../dist/apollo')
module.exports = require('../dist/cjs/apollo/index.js')
32 changes: 17 additions & 15 deletions packages/web/build.mts
Original file line number Diff line number Diff line change
@@ -1,37 +1,41 @@
// import { writeFileSync } from 'node:fs'

import {
build,
defaultBuildOptions,
defaultIgnorePatterns,
} from '@redwoodjs/framework-tools'
import { writeFileSync } from 'node:fs'

// CJS build
/**
* Notes:
* - we don't build the webpack entry point in CJS, because it produces a double wrapped module
* instead we use the ESM version (see ./webpackEntry in package.json). The double wrapping happens
* when you set type: module in package.json, and occurs on the App & Routes import from the project.
* - we build bins in CJS, until projects fully switch to ESM (or we produce .mts files) this is probably
* the better option
*/
await build({
entryPointOptions: {
ignore: [...defaultIgnorePatterns],
ignore: [...defaultIgnorePatterns, 'src/__typetests__/**', 'src/entry/**'],
},
buildOptions: {
...defaultBuildOptions,
// ⭐ No special tsconfig here
// outdir: 'dist/cjs', DONT DO THIS JUST YET
outdir: 'dist',
// ⭐ No special build tsconfig in this package
outdir: 'dist/cjs',
packages: 'external',
},
})

/** THIS IS IN PART 2 ~ making this a dual module
Will enable in follow up PR

ESM build
// ESM build
await build({
entryPointOptions: {
ignore: [...defaultIgnorePatterns, 'src/entry/**'],
// @NOTE: building the cjs bins only...
// I haven't tried esm bins yet...
ignore: [...defaultIgnorePatterns, 'src/bins/**', 'src/__typetests__/**'],
},
buildOptions: {
...defaultBuildOptions,
// ⭐ No special tsconfig here
// tsconfig: 'tsconfig.build.json',
// ⭐ No special build tsconfig in this package
format: 'esm',
packages: 'external',
},
Expand All @@ -44,5 +48,3 @@ writeFileSync('dist/cjs/package.json', JSON.stringify({ type: 'commonjs' }))
// Place a package.json file with `type: module` in the dist/esm folder so that
// all .js files are treated as ES Module files.
writeFileSync('dist/package.json', JSON.stringify({ type: 'module' }))

*/
71 changes: 62 additions & 9 deletions packages/web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "@redwoodjs/web",
"version": "7.0.0",
"type": "module",
"repository": {
"type": "git",
"url": "git+https://github.com/redwoodjs/redwood.git",
Expand All @@ -10,14 +11,66 @@
"main": "./dist/index.js",
"types": "dist/index.d.ts",
"bin": {
"cross-env": "./dist/bins/cross-env.js",
"msw": "./dist/bins/msw.js",
"redwood": "./dist/bins/redwood.js",
"rw": "./dist/bins/redwood.js",
"rwfw": "./dist/bins/rwfw.js",
"storybook": "./dist/bins/storybook.js",
"tsc": "./dist/bins/tsc.js",
"webpack": "./dist/bins/webpack.js"
"cross-env": "./dist/cjs/bins/cross-env.js",
"msw": "./dist/cjs/bins/msw.js",
"redwood": "./dist/cjs/bins/redwood.js",
"rw": "./dist/cjs/bins/redwood.js",
"rwfw": "./dist/cjs/bins/rwfw.js",
"storybook": "./dist/cjs/bins/storybook.js",
"tsc": "./dist/cjs/bins/tsc.js",
"webpack": "./dist/cjs/bins/webpack.js"
},
"exports": {
".": {
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
},
"./serverInject": {
"require": "./dist/cjs/components/ServerInject.js",
"import": "./dist/components/ServerInject.js",
"types": "./dist/components/ServerInject.d.ts",
"default": "./dist/components/ServerInject.js"
},
"./dist/components/*": {
"require": "./dist/cjs/components/*.js",
"import": "./dist/components/*.js"
},
"./dist/apollo/suspense": {
"require": "./dist/cjs/apollo/suspense.js",
"import": "./dist/apollo/suspense.js"
},
"./dist/apollo/sseLink": {
"require": "./dist/cjs/apollo/sseLink.js",
"import": "./dist/apollo/sseLink.js"
},
"./dist/graphql.js": {
"require": "./dist/cjs/graphql.js",
"import": "./dist/graphql.js"
},
"./webpackEntry": {
"default": "./dist/entry/index.js"
},
"./toast": {
"require": "./dist/cjs/toast/index.js",
"import": "./dist/toast/index.js",
"types": "./dist/toast/index.d.ts"
},
"./apollo": {
"require": "./dist/cjs/apollo/index.js",
"import": "./dist/apollo/index.js",
"types": "./dist/apollo/index.d.ts",
"default": "./dist/cjs/apollo/index.js"
},
"./forceEsmApollo": {
"require": "./dist/apollo/index.js",
"import": "./dist/apollo/index.js"
}
},
"files": [
"dist",
Expand All @@ -28,7 +81,7 @@
"scripts": {
"build": "tsx ./build.mts && yarn build:types",
"build:pack": "yarn pack -o redwoodjs-web.tgz",
"build:types": "tsc --build --verbose tsconfig.json",
"build:types": "tsc --build --verbose ./tsconfig.json ./tsconfig.types-cjs.json",
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx\" --ignore dist --exec \"yarn build\"",
"prepublishOnly": "NODE_ENV=production yarn build",
"test": "vitest run",
Expand Down
2 changes: 1 addition & 1 deletion packages/web/src/__typetests__/cellProps.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// These are normally auto-imported by babel
import React from 'react'

import gql from 'graphql-tag'
import { gql } from 'graphql-tag'
import { describe, expect, test } from 'tstyche'

import type { CellProps, CellSuccessProps } from '@redwoodjs/web'
Expand Down
8 changes: 5 additions & 3 deletions packages/web/src/apollo/fragmentRegistry.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as apolloClient from '@apollo/client'
import type { UseFragmentResult } from '@apollo/client'
import type { FragmentRegistryAPI } from '@apollo/client/cache'
import { createFragmentRegistry } from '@apollo/client/cache'
import { getFragmentDefinitions } from '@apollo/client/utilities'
// @ts-expect-error Force import cjs module
import { createFragmentRegistry } from '@apollo/client/cache/cache.cjs'
import type { FragmentRegistryAPI } from '@apollo/client/cache/index.js'
// @ts-expect-error Force import cjs module
import { getFragmentDefinitions } from '@apollo/client/utilities/utilities.cjs'
import type { DocumentNode } from 'graphql'

export type FragmentIdentifier = string | number
Expand Down
Loading
Loading