Skip to content

Commit

Permalink
refactor: remove FOUC handling
Browse files Browse the repository at this point in the history
As it now handled directly by adonisjs/vite. See adonisjs/vite#12
  • Loading branch information
Julien-R44 committed Mar 25, 2024
1 parent 082caa4 commit 0b25202
Show file tree
Hide file tree
Showing 6 changed files with 1 addition and 228 deletions.
97 changes: 1 addition & 96 deletions src/server_renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,9 @@
*/

import { Vite } from '@adonisjs/vite'
import type { ModuleNode } from 'vite'

import type { PageObject, ResolvedConfig } from './types.js'

const styleFileRE = /\.(css|less|sass|scss|styl|stylus|pcss|postcss)($|\?)/

/**
* Responsible for rendering page on the server
*
Expand All @@ -27,67 +24,6 @@ export class ServerRenderer {
protected vite?: Vite
) {}

/**
* If the module is a style module
*/
#isStyle(mod: ModuleNode) {
if (styleFileRE.test(mod.url) || (mod.id && /\?vue&type=style/.test(mod.id))) {
return true
}
return false
}

/**
* Collect CSS files from the module graph recursively
*/
#collectCss(
mod: ModuleNode,
styleUrls: Set<string>,
visitedModules: Set<string>,
importer?: ModuleNode
): void {
if (!mod.url) return

/**
* Prevent visiting the same module twice
*/
if (visitedModules.has(mod.url)) return
visitedModules.add(mod.url)

if (this.#isStyle(mod) && (!importer || !this.#isStyle(importer))) {
if (mod.url.startsWith('/')) {
styleUrls.add(mod.url)
} else if (mod.url.startsWith('\0')) {
// virtual modules are prefixed with \0
styleUrls.add(`/@id/__x00__${mod.url.substring(1)}`)
} else {
styleUrls.add(`/@id/${mod.url}`)
}
}

mod.importedModules.forEach((dep) => this.#collectCss(dep, styleUrls, visitedModules, mod))
}

/**
* Generate the preload tag for a CSS file
*/
#getPreloadTag(href: string) {
return `<link rel="stylesheet" href="${href}" />`
}

/**
* Find a page module from the entrypoint module
*
* The implementation is dumb, we are just looking for the first module
* imported by the entrypoint module that matches the regex
*/
#findPageModule(entryMod: ModuleNode | undefined, pageObject: PageObject) {
const pattern = `${pageObject.component.replace(/\//g, '\\/')}.(tsx|vue|svelte|jsx|ts|js)$`
const regex = new RegExp(pattern)

return [...(entryMod?.ssrImportedModules || [])].find((dep) => regex.test(dep.url))
}

/**
* Render the page on the server
*
Expand All @@ -96,7 +32,6 @@ export class ServerRenderer {
*/
async render(pageObject: PageObject) {
let render: { default: (page: any) => Promise<{ head: string; body: string }> }
let preloadTags: string[] = []
const devServer = this.vite?.getDevServer()

/**
Expand All @@ -106,35 +41,6 @@ export class ServerRenderer {
if (devServer) {
const runtime = await this.vite!.createRuntime()
render = await runtime.executeEntrypoint(this.config.ssr.entrypoint!)

/**
* We need to collect the CSS files to preload them
* Otherwise, we gonna have a FOUC each time we full reload the page
*
* First, we need to get the client-side entrypoint module
*/
const entryMod = devServer.moduleGraph.getModuleById(this.config.entrypoint)

/**
* We should also get the page component that will be rendered. So
* we analyze the module graph to find the module that matches the
* page component
*
* Then execute it with Vite Runtime so the module graph is populated
*/
const pageMod = this.#findPageModule(entryMod, pageObject)
if (pageMod) await runtime.executeUrl(pageMod.url)

/**
* Then we can finally collect the CSS files
*/
const preloadUrls = new Set<string>()
const visitedModules = new Set<string>()

if (pageMod) this.#collectCss(pageMod, preloadUrls, visitedModules)
if (entryMod) this.#collectCss(entryMod, preloadUrls, visitedModules)

preloadTags = Array.from(preloadUrls).map(this.#getPreloadTag)
} else {
/**
* Otherwise, just import the SSR bundle
Expand All @@ -146,7 +52,6 @@ export class ServerRenderer {
* Call the render function and return head and body
*/
const result = await render.default(pageObject)
const head = preloadTags.concat(result.head)
return { head, body: result.body }
return { head: [result.head], body: result.body }
}
}
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ export interface ResolvedConfig {
rootView: string
versionCache: VersionCache
sharedData: SharedData
entrypoint: string
ssr: {
enabled: boolean
entrypoint: string
Expand Down
13 changes: 0 additions & 13 deletions tests/define_config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,11 @@

import { join } from 'node:path'
import { test } from '@japa/runner'
import { slash } from '@poppinss/utils'

import { defineConfig } from '../index.js'
import { setupApp } from '../tests_helpers/index.js'

test.group('Define Config', () => {
test('detect entrypoint automatically - "{$self}"')
.with(['inertia/app/app.tsx', 'resources/app.ts', 'resources/app.tsx'])
.run(async ({ assert, fs }, filePath) => {
const { app } = await setupApp()
const configProvider = defineConfig({})
await fs.create(filePath, '')

const result = await configProvider.resolver(app)

assert.deepEqual(result.entrypoint, slash(join(app.makePath(filePath))))
})

test('detect bundle automatically - "{$self}"')
.with(['ssr/ssr.js', 'ssr/ssr.mjs'])
.run(async ({ assert, fs }, filePath) => {
Expand Down
108 changes: 0 additions & 108 deletions tests/inertia.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
* file that was distributed with this source code.
*/

import { join } from 'node:path'
import { test } from '@japa/runner'
import { Vite } from '@adonisjs/vite'
import { HttpContext } from '@adonisjs/core/http'
Expand Down Expand Up @@ -388,110 +387,3 @@ test.group('Inertia | Ssr', () => {
assert.deepEqual(result.props.page.version, '1')
})
})

test.group('Inertia | Ssr | CSS Preloading', () => {
test('collect and preload css files of entrypoint', async ({ assert, fs }) => {
setupViewMacroMock()
const vite = await setupVite({ build: { rollupOptions: { input: 'foo.ts' } } })

await fs.create(
'foo.ts',
`
import './style.css'
export default () => ({ head: "head", body: "foo.ts" })
`
)

await fs.create('style.css', 'body { color: red }')

const inertia = await new InertiaFactory()
.withVite(vite)
.merge({
config: {
entrypoint: join(fs.basePath, 'foo.ts'),
ssr: { enabled: true, entrypoint: 'foo.ts' },
},
})
.create()

const result: any = await inertia.render('foo')

assert.deepEqual(result.props.page.ssrHead, [
'<link rel="stylesheet" href="/style.css" />',
'head',
])
})

test('collect recursively css files of entrypoint', async ({ assert, fs }) => {
setupViewMacroMock()
const vite = await setupVite({ build: { rollupOptions: { input: 'foo.ts' } } })

await fs.create(
'foo.ts',
`
import './foo2.ts'
import './style.css'
export default () => ({ head: "head", body: "foo.ts" })
`
)

await fs.create('foo2.ts', `import './style2.css'`)
await fs.create('style.css', 'body { color: red }')
await fs.create('style2.css', 'body { color: blue }')

const inertia = await new InertiaFactory()
.withVite(vite)
.merge({
config: {
entrypoint: join(fs.basePath, 'foo.ts'),
ssr: { enabled: true, entrypoint: 'foo.ts', pages: ['foo'] },
},
})
.create()

const result: any = await inertia.render('foo')

assert.deepEqual(result.props.page.ssrHead, [
'<link rel="stylesheet" href="/style2.css" />',
'<link rel="stylesheet" href="/style.css" />',
'head',
])
})

test('collect css rendered page', async ({ assert, fs }) => {
setupViewMacroMock()
const vite = await setupVite({ build: { rollupOptions: { input: 'foo.ts' } } })

await fs.create(
'app.ts',
`
import './style.css'
import.meta.glob('./pages/**/*.tsx')
export default () => ({ head: "head", body: "foo.ts" })
`
)
await fs.create('style.css', 'body { color: red }')

await fs.create('./pages/home/main.tsx', `import './style2.css'`)
await fs.create('./pages/home/style2.css', 'body { color: blue }')

const inertia = await new InertiaFactory()
.withVite(vite)
.merge({
config: {
entrypoint: join(fs.basePath, 'app.ts'),
ssr: { enabled: true, entrypoint: 'app.ts' },
},
})
.create()

const result: any = await inertia.render('home/main')

assert.deepEqual(result.props.page.ssrHead, [
'<link rel="stylesheet" href="/pages/home/style2.css" />',
'<link rel="stylesheet" href="/style.css" />',
'head',
])
})
})
7 changes: 0 additions & 7 deletions tests/middleware.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: new VersionCache(new URL(import.meta.url), '1'),
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand All @@ -47,7 +46,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: new VersionCache(new URL(import.meta.url), '1'),
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand Down Expand Up @@ -77,7 +75,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: new VersionCache(new URL(import.meta.url), '1'),
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand Down Expand Up @@ -107,7 +104,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: new VersionCache(new URL(import.meta.url), '1'),
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand Down Expand Up @@ -135,7 +131,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: new VersionCache(new URL(import.meta.url), '1'),
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand All @@ -157,7 +152,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: version,
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand Down Expand Up @@ -189,7 +183,6 @@ test.group('Middleware', () => {
const middleware = new InertiaMiddleware({
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
versionCache: version,
ssr: { enabled: false, bundle: '', entrypoint: '' },
})
Expand Down
3 changes: 0 additions & 3 deletions tests/plugins/api_client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ test.group('Japa plugin | Api Client', (group) => {
versionCache: new VersionCache(new URL(import.meta.url), '1'),
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
ssr: { enabled: false, bundle: '', entrypoint: '' },
})

Expand Down Expand Up @@ -116,7 +115,6 @@ test.group('Japa plugin | Api Client', (group) => {
versionCache: new VersionCache(new URL(import.meta.url), '1'),
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
ssr: { enabled: false, bundle: '', entrypoint: '' },
})

Expand Down Expand Up @@ -151,7 +149,6 @@ test.group('Japa plugin | Api Client', (group) => {
versionCache: new VersionCache(new URL(import.meta.url), '1'),
rootView: 'root',
sharedData: {},
entrypoint: 'app.ts',
ssr: { enabled: false, bundle: '', entrypoint: '' },
})

Expand Down

0 comments on commit 0b25202

Please sign in to comment.