Skip to content

Commit

Permalink
chore(esm): convert @redwoodjs/project-config to ESM (redwoodjs#9870)
Browse files Browse the repository at this point in the history
I'm still working through a few things.

The motivation for tackling `@redwoodjs/project-config` first was 1)
most of our other package's depend on it 2) it's small 3) it would make
merging the PR that converts the CLI's Jest tests to Vitest easier
because Vitest can't mock require (see
redwoodjs#9863).

I used
[`arethetypeswrong/cli`](https://github.com/arethetypeswrong/arethetypeswrong.github.io)
extensively. Right now I'm deeming the "Masquerading as ESM" error it
emits acceptable. The code between the ESM and CJS files doesn't differ
in functionality, only syntax; shipping two declaration copies of all
the declaration files is shipping extra code. Mark Erikson did something
similar at first at least here:

> Unfortunately, no build tool that I knew of at that time did this by
default, and the idea of shipping 99%-duplicate typedefs bothered me.
So, I opted to not try to fix this "FalseCJS" issue for our packages (at
least for the time being).

(Source:
https://blog.isquaredsoftware.com/2023/08/esm-modernization-lessons/#typescript-declarations.)

Note that FalseCJS's fancier name is "Masquerading as CJS". We have
"Masquerading as ESM", not CJS. I'm not sure if it's an issue that it's
flipped yet.

```
$ attw ./redwoodjs-project-config.tgz 

@redwoodjs/project-config v6.0.7

Build tools:
- typescript@5.3.3
- esbuild@0.19.9

👺 Import resolved to an ESM type declaration file, but a CommonJS JavaScript file. https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md


┌───────────────────┬─────────────────────────────┐
│                   │ "@redwoodjs/project-config" │
├───────────────────┼─────────────────────────────┤
│ node10            │ 🟢                          │
├───────────────────┼─────────────────────────────┤
│ node16 (from CJS) │ 👺 Masquerading as ESM      │
├───────────────────┼─────────────────────────────┤
│ node16 (from ESM) │ 🟢 (ESM)                    │
├───────────────────┼─────────────────────────────┤
│ bundler           │ 🟢                          │
└───────────────────┴─────────────────────────────┘
```

Regarding the `.js` extensions (which are necessary for relative imports
in ESM) in TS code, see redwoodjs#8456.
  • Loading branch information
jtoar committed Jan 22, 2024
1 parent 49347fd commit 68ed27a
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 36 deletions.
28 changes: 28 additions & 0 deletions packages/project-config/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* eslint-disable import/no-extraneous-dependencies */

import * as esbuild from 'esbuild'

const options = {
entryPoints: ['./src/index.ts'],
outdir: 'dist',

platform: 'node',
target: ['node20'],
bundle: true,
packages: 'external',

logLevel: 'info',
metafile: true,
}

await esbuild.build({
...options,
format: 'esm',
outExtension: { '.js': '.mjs' },
})

await esbuild.build({
...options,
format: 'cjs',
outExtension: { '.js': '.cjs' },
})
22 changes: 0 additions & 22 deletions packages/project-config/build.mjs

This file was deleted.

7 changes: 5 additions & 2 deletions packages/project-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,18 @@
"directory": "packages/project-config"
},
"license": "MIT",
"type": "module",
"exports": {
".": "./dist/index.js"
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"default": "./dist/index.cjs"
},
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "yarn node ./build.mjs && run build:types",
"build": "yarn node ./build.js && run build:types",
"build:pack": "yarn pack -o redwoodjs-project-config.tgz",
"build:types": "tsc --build --verbose",
"build:watch": "nodemon --watch src --ext \"js,ts,tsx\" --ignore dist --exec \"yarn build\"",
Expand Down
2 changes: 1 addition & 1 deletion packages/project-config/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import toml from '@iarna/toml'
import merge from 'deepmerge'
import { env as envInterpolation } from 'string-env-interpolation'

import { getConfigPath } from './configPath'
import { getConfigPath } from './configPath.js'

export enum TargetEnum {
NODE = 'node',
Expand Down
2 changes: 1 addition & 1 deletion packages/project-config/src/configPath.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { findUp } from './findUp'
import { findUp } from './findUp.js'

const CONFIG_FILE_NAME = 'redwood.toml'

Expand Down
8 changes: 4 additions & 4 deletions packages/project-config/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export * from './config'
export * from './configPath'
export * from './paths'
export * from './findUp'
export * from './config.js'
export * from './configPath.js'
export * from './paths.js'
export * from './findUp.js'
4 changes: 2 additions & 2 deletions packages/project-config/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import path from 'path'

import fg from 'fast-glob'

import { getConfig } from './config'
import { getConfigPath } from './configPath'
import { getConfig } from './config.js'
import { getConfigPath } from './configPath.js'

export interface NodeTargetPaths {
base: string
Expand Down
2 changes: 2 additions & 0 deletions packages/project-config/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"extends": "../../tsconfig.compilerOption.json",
"compilerOptions": {
"moduleResolution": "NodeNext",
"module": "NodeNext",
"baseUrl": ".",
"rootDir": "src",
"outDir": "dist",
Expand Down
4 changes: 2 additions & 2 deletions packages/vite/bins/rw-vite-dev.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { createServer } from 'vite'
import yargsParser from 'yargs-parser'

import projectConfig from '@redwoodjs/project-config'
import { getPaths } from '@redwoodjs/project-config'

const rwPaths = projectConfig.getPaths()
const rwPaths = getPaths()

const startDevServer = async () => {
const configFile = rwPaths.web.viteConfig
Expand Down
3 changes: 1 addition & 2 deletions packages/vite/src/__tests__/viteNestedPages.test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { transformWithEsbuild } from 'vite'
import { test, describe, beforeEach, afterAll, beforeAll, it, expect, vi } from 'vitest'

import * as babel from '@babel/core'
import projectConfig from '@redwoodjs/project-config'
import { getPaths } from '@redwoodjs/project-config'

import {
Flags,
Expand Down Expand Up @@ -41,7 +41,6 @@ async function transform(srcPath: string) {
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const FIXTURE_PATH = path.join(__dirname, 'fixtures/nestedPages')
const { getPaths } = projectConfig

test('transform', async () => {
vi.spyOn(fs, 'readFileSync').mockImplementationOnce(() => {
Expand Down

0 comments on commit 68ed27a

Please sign in to comment.