Skip to content

Commit 290403b

Browse files
committedAug 23, 2023
fix: warn users that still use CJS
1 parent cf40d19 commit 290403b

File tree

12 files changed

+125
-26
lines changed

12 files changed

+125
-26
lines changed
 

‎docs/headingsDetached.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,8 @@ const headingsDetached = [
309309
title: "Vite's Lazy Transpiling",
310310
url: '/lazy-transpiling'
311311
},
312+
{
313+
title: 'CJS',
314+
url: '/CJS'
315+
}
312316
] satisfies HeadingDetachedDefinition[]

‎docs/pages/CJS.page.server.mdx

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
While you can use vite-plugin-ssr with
2+
[CJS code](https://nodejs.org/api/modules.html#modules-commonjs-modules:~:text=CommonJS%20modules%20are%20the%20original%20way%20to%20package%20JavaScript%20code%20for%20Node.js.%20Node.js%20also%20supports%20the%20ECMAScript%20modules%20standard%20used%20by%20browsers%20and%20other%20JavaScript%20runtimes.),
3+
we recommend writing
4+
[ESM code](https://nodejs.org/api/esm.html#modules-ecmascript-modules:~:text=ECMAScript%20modules%20are%20the%20official%20standard%20format%20to%20package%20JavaScript%20code%20for%20reuse.%20Modules%20are%20defined%20using%20a%20variety%20of%20import%20and%20export%20statements.)
5+
instead.
6+
7+
> The code you write that is processed by Vite is already ESM. But [some of your server code may not be processed by Vite](https://github.com/brillout/vite-plugin-ssr/issues/562) and may be CJS.
8+
9+
If you get the following warning:
10+
11+
```
12+
[vite-plugin-ssr][Warning] We recommend setting package.json#type to "module" (and therefore
13+
writing ESM code instead of CJS code)
14+
```
15+
16+
Then, in order to remove the warning, add this to your `package.json`:
17+
18+
```json5
19+
// package.json
20+
{
21+
// ...
22+
type: "module"
23+
}
24+
```
25+
26+
This [makes Node.js treat all .js files as ESM](https://nodejs.org/docs/latest-v13.x/api/esm.html#esm_package_json_type_field:~:text=Files%20ending%20with%20.js%20will%20be%20loaded%20as%20ES%20modules%20when%20the%20nearest%20parent%20package.json%20file%20contains%20a%20top%2Dlevel%20field%20%22type%22%20with%20a%20value%20of%20%22module%22.).
27+
28+
This means that, if you have .js files written in CJS, then you'll have to migrate them to ESM. For example:
29+
30+
```js
31+
-// CJS code
32+
-const express = require('express')
33+
-const { renderPage } = require('vite-plugin-ssr/server')
34+
+// ESM code
35+
+import express from 'express'
36+
+import { renderPage } from 'vite-plugin-ssr/server'
37+
```
38+
39+
> An escape hatch is to use [the `.cjs` and `.mjs` file extensions](https://nodejs.org/api/esm.html#enabling:~:text=Authors%20can%20tell%20Node.js%20to%20use%20the%20ECMAScript%20modules%20loader%20via%20the%20.mjs%20file%20extension), enabling you to determine/change the module system on a file-by-file basis regardless of whether `package.json#type` is set to `"module"` or `"commonjs"`.
40+
41+
> You still want to use CJS? Let us know why and we'll create a new `config.disableCJSWarning`.

‎examples/react/.testRun.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,26 @@ import {
99
autoRetry,
1010
fetchHtml,
1111
getServerUrl,
12-
testScreenshotFixture
12+
testScreenshotFixture,
13+
expectLog
1314
} from '@brillout/test-e2e'
1415
import path from 'path'
1516
import url from 'url'
1617
import { createRequire } from 'module'
1718

18-
function testRun(cmd: 'npm run dev' | 'npm run preview' | 'npm run prod') {
19+
function testRun(cmd: 'npm run dev' | 'npm run preview' | 'npm run prod', isCJS?: true) {
1920
run(cmd)
2021

2122
test('page content is rendered to HTML', async () => {
2223
const html = await fetchHtml('/')
2324
expect(html).toContain('<h1>Welcome</h1>')
2425
expectHtmlCommon(html)
26+
if (isCJS) {
27+
expectLog(
28+
'package.json#type to "module" (and therefore writing ESM code instead of CJS code), see https://vite-plugin-ssr.com/CJS',
29+
(log) => log.logSource === 'stderr'
30+
)
31+
}
2532
})
2633

2734
test('page is rendered to the DOM and interactive', async () => {

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"devDependencies": {
4242
"@brillout/bump-dependencies": "^0.1.1",
4343
"@brillout/dev-my-dep": "^0.1.5",
44-
"@brillout/test-e2e": "^0.5.12",
44+
"@brillout/test-e2e": "^0.5.13",
4545
"@brillout/test-types": "^0.1.6",
4646
"vitest": "^0.34.1"
4747
},

‎pnpm-lock.yaml

+4-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/cjs/test-dev.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import { testRun } from '../../examples/react/.testRun'
1+
import { testRun } from './testRun'
22
testRun('npm run dev')

‎test/cjs/test-prod.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import { testRun } from '../../examples/react/.testRun'
1+
import { testRun } from './testRun'
22
testRun('npm run prod')

‎test/cjs/testRun.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export { testRun }
2+
3+
import { testRun as testRun_ } from '../../examples/react/.testRun'
4+
5+
type Cmd = Parameters<typeof testRun_>[0]
6+
function testRun(cmd: Cmd) {
7+
testRun_(cmd, true)
8+
}

‎vite-plugin-ssr/node/plugin/plugins/commonConfig.ts

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
export { commonConfig }
22

33
import type { Plugin, ResolvedConfig } from 'vite'
4-
import { assert, assertWarning, isValidPathAlias } from '../utils.js'
4+
import { assert, assertWarning, findUserPackageJsonPath, isValidPathAlias } from '../utils.js'
55
import { assertRollupInput } from './buildConfig.js'
66
import { installRequireShim_setUserRootDir } from '@brillout/require-shim'
7+
import pc from '@brillout/picocolors'
8+
import path from 'path'
9+
import { createRequire } from 'module'
10+
// @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
11+
const importMetaUrl: string = import.meta.url
12+
const require_ = createRequire(importMetaUrl)
713

814
function commonConfig(): Plugin[] {
915
return [
@@ -31,6 +37,7 @@ function commonConfig(): Plugin[] {
3137
workaroundCI(config)
3238
assertRollupInput(config)
3339
assertResolveAlias(config)
40+
assertEsm(config.root)
3441
}
3542
}
3643
}
@@ -98,3 +105,21 @@ function getAliases(config: ResolvedConfig) {
98105
return alias
99106
}
100107
}
108+
109+
function assertEsm(userViteRoot: string) {
110+
const packageJsonPath = findUserPackageJsonPath(userViteRoot)
111+
if (!packageJsonPath) return
112+
const packageJson = require_(packageJsonPath)
113+
let dir = path.dirname(packageJsonPath)
114+
if (dir !== '/') {
115+
assert(!dir.endsWith('/'))
116+
dir = dir + '/'
117+
}
118+
assert(dir.endsWith('/'))
119+
dir = pc.dim(dir)
120+
assertWarning(
121+
packageJson.type === 'module',
122+
`We recommend setting ${dir}package.json#type to "module" (and therefore writing ESM code instead of CJS code), see https://vite-plugin-ssr.com/CJS`,
123+
{ onlyOnce: true }
124+
)
125+
}

‎vite-plugin-ssr/node/plugin/plugins/config/stemUtils.ts

+9-16
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,16 @@ export { getStemPackages }
44
export type { StemPackage }
55

66
import path from 'path'
7-
import { assert, assertUsage, assertWarning, toPosixPath, assertPosixPath, getDependencyRootDir } from '../../utils.js'
7+
import {
8+
assert,
9+
assertUsage,
10+
assertWarning,
11+
toPosixPath,
12+
assertPosixPath,
13+
getDependencyRootDir,
14+
findUserPackageJsonPath
15+
} from '../../utils.js'
816
import { import_ } from '@brillout/import'
9-
import fs from 'fs'
1017
import { createRequire } from 'module'
1118
// @ts-ignore Shimed by dist-cjs-fixup.js for CJS build.
1219
const importMetaUrl: string = import.meta.url
@@ -68,20 +75,6 @@ function findUserRootDir(userAppRootDir: string): string {
6875
assertUsage(userPkgJsonPath, `Couldn't find package.json in any parent directory starting from ${userAppRootDir}`)
6976
return toPosixPath(path.dirname(userPkgJsonPath))
7077
}
71-
function findUserPackageJsonPath(userAppRootDir: string): null | string {
72-
let dir = userAppRootDir
73-
while (true) {
74-
const configFilePath = path.join(dir, './package.json')
75-
if (fs.existsSync(configFilePath)) {
76-
return configFilePath
77-
}
78-
const dirPrevious = dir
79-
dir = path.dirname(dir)
80-
if (dir === dirPrevious) {
81-
return null
82-
}
83-
}
84-
}
8578

8679
function getStemPkgNames(userPkgJson: UserPkgJson): string[] {
8780
const stemPkgNames = Object.keys(userPkgJson.dependencies ?? {}).filter((depName) => {

‎vite-plugin-ssr/node/plugin/utils.ts

+1
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ export * from '../../utils/escapeRegex.js'
2323
export * from '../../utils/stripAnsi.js'
2424
export * from '../../utils/trimWithAnsi.js'
2525
export * from '../../utils/removeEmptyLines.js'
26+
export * from '../../utils/findUserPackageJsonPath.js'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
export { findUserPackageJsonPath }
2+
3+
import path from 'path'
4+
import fs from 'fs'
5+
6+
function findUserPackageJsonPath(userDir: string): null | string {
7+
let dir = userDir
8+
while (true) {
9+
const configFilePath = path.join(dir, './package.json')
10+
if (fs.existsSync(configFilePath)) {
11+
// return toPosixPath(configFilePath)
12+
return configFilePath
13+
}
14+
const dirPrevious = dir
15+
dir = path.dirname(dir)
16+
if (dir === dirPrevious) {
17+
return null
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)
Please sign in to comment.