Skip to content

Commit

Permalink
fix: server module loader
Browse files Browse the repository at this point in the history
  • Loading branch information
arpowers committed Feb 12, 2022
1 parent a0f4c63 commit db53e54
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 11,996 deletions.
1 change: 0 additions & 1 deletion @core/api/package.json
Expand Up @@ -25,7 +25,6 @@
"consola": "^2.15.3",
"dayjs": "^1.8.16",
"deepmerge": "^4.1.1",
"events": "^3.2.0",
"fast-json-stable-stringify": "^2.1.0",
"fast-safe-stringify": "^2.1.1",
"front-matter": "^4.0.0",
Expand Down
95 changes: 62 additions & 33 deletions @core/render/buildPlugins.ts
@@ -1,6 +1,8 @@
import { ResolveIdResult, LoadResult } from "rollup"
import { serverConfigSetting } from "@factor/server/config"
import * as esLexer from "es-module-lexer"
import * as cjsLexer from "cjs-module-lexer"
import * as vite from "vite"

export type ServerModuleDef = {
id: string
exports?: string[]
Expand All @@ -25,57 +27,84 @@ export const getServerOnlyModules = (): ServerModuleDef[] => {
{ id: "body-parser" },
{ id: "cors" },
{ id: "helmet" },

{ id: "fast-safe-stringify" },
{ id: "module", exports: ["createRequire"] },
...s,
]
}

const getReplacedModule = (opts: {
id?: string
src: string
type: "comment" | "map"
}): string => {
const { src, id = "?" } = opts

const fileExports: string[] = []

if (src.includes("exports")) {
const { exports: cjsExports } = cjsLexer.parse(src)
fileExports.push(...cjsExports)
} else {
const [_imports, esExports] = esLexer.parse(src)
fileExports.push(...esExports)
}

const modExports = fileExports.filter((_) => _ != "default")

const mock = `{}`

const namedExports =
modExports.length > 0
? modExports.map((_) => `export const ${_} = ${mock}`).join(`\n`)
: ""

const newSource = [
`// replaced file: ${id}`,
`export default ${mock}`,
`${namedExports}`,
].join(`\n`)

return newSource
}
/**
* Remove and replace modules only meant for server
*
* /0 prefix prevents other plugins from messing with module
* https://rollupjs.org/guide/en/#conventions
*/
export const getCustomBuildPlugins = (): vite.Plugin[] => {
export const getCustomBuildPlugins = async (): Promise<vite.Plugin[]> => {
const serverOnlyModules = getServerOnlyModules()

const fullServerModules = serverOnlyModules.map((_) => {
return { ..._, exports: _.exports || [], resolvedId: `\0${_.id}` }
return {
..._,
resolvedId: `\0${_.id}`,
}
})

await Promise.all([esLexer.init, cjsLexer.init()])

const plugins: vite.Plugin[] = [
{
name: "serverOnly",
enforce: "pre",
transform(src: string, id: string) {
const match = src.match(/server-only-file/)

if (match) {
return {
code: `// server only file: ${id}
export default {}`,
map: null,
}
}
},
},
{
name: "serverModuleReplacer", // required, will show up in warnings and errors
enforce: "pre",
resolveId(id: string): ResolveIdResult {
const found = fullServerModules.find((_) => _.id == id)
if (found) {
return found.resolvedId
}
},
load(id: string): LoadResult {
const found = fullServerModules.find((_) => _.resolvedId == id)
if (found) {
return `// module ${id} replaced
const _ = () => "SERVER_ONLY_MODULE"
export default _
${found.exports.map((_) => `const ${_} = _\n`)}
export {${found.exports.map((_) => _).join(",")}}`
// resolveId(id: string): ResolveIdResult {
// const found = fullServerModules.find((_) => _.id == id)
// if (found) {
// return found.resolvedId
// }
// },
transform(src: string, id: string) {
const isServerPackage = fullServerModules.find((_) => {
return id.includes(`node_modules/${_.id}`)
})

const isServerFile = /server-only-file/.test(src)

if (isServerPackage || isServerFile) {
const code = getReplacedModule({ src, id, type: "map" })
return { code, map: null }
}
},
config: () => {
Expand Down

0 comments on commit db53e54

Please sign in to comment.