Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "blog",
"runtimeExecutable": "pnpm",
"runtimeArgs": ["blog"],
"port": 5173
}
]
}
7 changes: 7 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"permissions": {
"allow": [
"mcp__Claude_Preview__preview_start"
]
}
}
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
CI: true

runs-on: ubuntu-latest
container: cypress/included:9.2.0
container: cypress/included:15.13.0
steps:
- uses: actions/checkout@v2

Expand Down
33 changes: 33 additions & 0 deletions docs/cypress/e2e/docsearch.cypress.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,37 @@ describe('DocSearch', () => {
openSearchModalWithKeyboard()
closeSearchModal()
})

it('can search and navigate to a result', () => {
visitHome()
openSearchModal()

// Type a search query.
cy.get('.DocSearch-Input').type('hydration')
cy.get('.DocSearch-Hit', { timeout: 10000 }).should('exist')

// Click the first result.
cy.get('.DocSearch-Hit').first().click()

// Verify navigation happened — should be on a page about hydration.
cy.url().should('include', 'hydration')
cy.get('h1').invoke('text').then((text) => {
expect(text.toLowerCase()).to.include('hydration')
})
})

it('search works after turbo navigation', () => {
visitHome()

// Navigate to another page via sidebar link.
navigateTo('FAQs')
assertPage({ title: 'FAQs' })

// Search should still work after turbo navigation.
openSearchModalWithKeyboard()
closeSearchModal()

openSearchModal()
closeSearchModal()
})
})
10 changes: 10 additions & 0 deletions docs/cypress/e2e/home.cypress.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,14 @@ describe('The Home Page', () => {

goBackHome()
})

it('serves a valid pwa-manifest.json', () => {
cy.request('/pwa-manifest.json').then((response) => {
expect(response.status).to.eq(200)
expect(response.headers['content-type']).to.include('application/json')
expect(response.body.name).to.eq('îles')
expect(response.body.theme_color).to.eq('#5C7E8F')
expect(response.body.icons).to.have.length(3)
})
})
})
5 changes: 3 additions & 2 deletions docs/cypress/e2e/sidebar.cypress.cy.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { visit, navigateTo, goBackHome, assertPage, waitForHydration } from './helpers'
import { assertPage, visit, visitHome, waitForHydration } from './helpers'

describe('Sidebar Toggle', () => {
const sidebar = () =>
Expand All @@ -24,7 +24,8 @@ describe('Sidebar Toggle', () => {
sidebarToggle().should('not.be.visible')
})

test.skipIf(process.env.CI)('can open in mobile', () => {
// test.skipIf(process.env.CI)('can open in mobile', () => {
it('can open in mobile', () => {
visitHome()
cy.viewport(500, 720)
visit('/guide/frameworks')
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"preact": "^10.24.3",
"preact-render-to-string": "^6.5.11",
"rehype-external-links": "^3.0.0",
"unocss": "^0.61.8",
"unocss": "^66.6.6",
"vite-plugin-inspect": "^0.8.7",
"vue-tsc": "^2.1.10"
},
Expand Down
6 changes: 3 additions & 3 deletions docs/scripts/test-cypress
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ set -e
cd "$(dirname "$0")/.."

echo '== Starting server =='
pnpm run preview &
pnpm exec iles preview --host 0.0.0.0 --port 3050 &

echo '== Waiting for server to respond... =='
pnpx wait-on http-get://localhost:3050 --delay 1000 --timeout 15000
pnpx wait-on http-get://localhost:3050 --delay 1000 --timeout 60000

echo '== Server ready! =='

pnpx cypress@10.6.0 run && echo '== Finished! =='
pnpx cypress@15.13.0 run && echo '== Finished! =='
2 changes: 1 addition & 1 deletion docs/src/components/TheSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export function onLoad () {

const [panel, bg] = [doc.getElementById('sidebar-panel')!, doc.getElementById('sidebar-background')!]

panel.classList.toggle('!-translate-x-0', open)
panel.style.setProperty('--un-translate-x', open ? '0' : null)

if (open) {
bg.classList.remove('hidden')
Expand Down
10 changes: 6 additions & 4 deletions iles.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { join } from 'pathe'

const testConfig = {
test: {
deps: {
inline: [
'@vue/devtools-api',
],
server: {
deps: {
inline: [
'@vue/devtools-api',
],
},
},
},
}
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@
"semver": "^7.6.3",
"tsx": "^4.19.2",
"typescript": "^5.6.3",
"vitest": "^2.1.4"
"vitest": "^4.1.0"
},
"pnpm": {
"overrides": {
"@typescript-eslint/typescript-estree": "8.5.0",
"esbuild": "0.24.0",
"vite": "5.4.10"
"vite": "8.0.0"
},
"peerDependencyRules": {
"allowedVersions": {
Expand Down
2 changes: 1 addition & 1 deletion packages/hydration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"svelte": "^5.1.13",
"tsup": "8.2.4",
"typescript": "^5.6.3",
"vite": "^5.4.10",
"vite": "^8.0.0",
"vue": "^3.5.12"
}
}
10 changes: 5 additions & 5 deletions packages/iles/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"lint:fix": "eslint . --fix"
},
"engines": {
"node": "^18.0.0 || >=20.0.0"
"node": ">=20.19.0 || >=22.12.0"
},
"keywords": [
"vite",
Expand All @@ -71,7 +71,7 @@
"@nuxt/devalue": "^2.0.2",
"@unhead/ssr": "^1.9.16",
"@unhead/vue": "^1.9.16",
"@vitejs/plugin-vue": "^5.1.4",
"@vitejs/plugin-vue": "^6.0.5",
"@vue/devtools-api": "^7.6.3",
"debug": "^4.3.5",
"deep-equal": "^2.2.3",
Expand All @@ -85,13 +85,13 @@
"picocolors": "^1.0.1",
"unist-util-visit": "^5.0.0",
"unplugin-vue-components": "^0.27.3",
"vite": "^5.4.10",
"vite": "^8.0.0",
"vue": "^3.5.12",
"vue-router": "^4.4.0"
},
"devDependencies": {
"@preact/preset-vite": "^2.9.1",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@sveltejs/vite-plugin-svelte": "^7.0.0",
"@types/debug": "^4.1.12",
"@types/fs-extra": "^11.0.4",
"@types/micromatch": "^4.0.9",
Expand All @@ -108,7 +108,7 @@
"mdast-util-mdxjs-esm": "^2.0.1",
"micromatch": "^4.0.7",
"npm-run-all": "^4.1.5",
"rollup": "^4.19.0",
"rolldown": "1.0.0-rc.9",
"semver": "^7.6.3",
"tinyglobby": "0.2.6",
"tsup": "8.2.4",
Expand Down
19 changes: 6 additions & 13 deletions packages/iles/src/client/app/hydration.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { useSSRContext } from 'vue'
import {
hydrateWhenIdle,
hydrateNow,
hydrateOnMediaQuery,
hydrateWhenVisible,
} from '@islands/hydration'

export function newHydrationId () {
if (import.meta.env.SSR) {
const context = useSSRContext()
Expand All @@ -27,12 +20,12 @@ export enum Hydrate {
}

export const hydrationFns = {
[Hydrate.WhenIdle]: hydrateWhenIdle.name,
[Hydrate.OnLoad]: hydrateNow.name,
[Hydrate.MediaQuery]: hydrateOnMediaQuery.name,
[Hydrate.SkipPrerender]: hydrateNow.name,
[Hydrate.WhenVisible]: hydrateWhenVisible.name,
[Hydrate.None]: hydrateNow.name,
[Hydrate.WhenIdle]: 'hydrateWhenIdle',
[Hydrate.OnLoad]: 'hydrateNow',
[Hydrate.MediaQuery]: 'hydrateOnMediaQuery',
[Hydrate.SkipPrerender]: 'hydrateNow',
[Hydrate.WhenVisible]: 'hydrateWhenVisible',
[Hydrate.None]: 'hydrateNow',
}

// Internal: Strategies that will hydrate instantly and don't need dynamic imports.
Expand Down
9 changes: 4 additions & 5 deletions packages/iles/src/node/build/bundle.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { promises as fs } from 'fs'
import type { RollupOutput } from 'rollup'
import type { RolldownOutput } from 'rolldown'
import type { Plugin } from 'vite'
import glob from 'fast-glob'
import { relative, dirname, resolve, join } from 'pathe'
Expand Down Expand Up @@ -55,17 +55,16 @@ async function bundleWithVite (config: AppConfig, entrypoints: string[] | Entryp
build: {
ssr,
cssCodeSplit: htmlBuild || !ssr,
minify: ssr ? false : 'esbuild',
minify: ssr,
emptyOutDir: ssr,
outDir: ssr ? config.tempDir : config.outDir,
sourcemap: false,
rollupOptions: {
rolldownOptions: {
input: entrypoints,
preserveEntrySignatures: htmlBuild ? undefined : 'allow-extension',
treeshake: htmlBuild,
},
},
} as ViteUserConfig)) as RollupOutput
} as ViteUserConfig)) as RolldownOutput
}

// Internal: Currently SSG supports a single stylesheet for all pages.
Expand Down
14 changes: 11 additions & 3 deletions packages/iles/src/node/build/chunks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import type { GetManualChunk, ManualChunkMeta } from 'rollup'
import type { GetModuleInfo } from 'rolldown'
import type { AppConfig } from '../shared'

interface ManualChunkMeta {
getModuleInfo: GetModuleInfo
}
type GetManualChunk = (id: string, meta: ManualChunkMeta) => string | void

export function extendManualChunks (config: AppConfig): GetManualChunk {
const userChunks = config.ssg.manualChunks
const cache = new Map<string, string | undefined>()
Expand All @@ -11,10 +16,13 @@ export function extendManualChunks (config: AppConfig): GetManualChunk {
vue: 'vendor-vue',
}
return (id, api) => {
const name = userChunks?.(id, api)
if (name) return name
// Internal chunks must take priority to ensure hydration works correctly.
// User manualChunks could inadvertently match hydration modules (e.g.
// id.includes('preact') also matches @islands/hydration/preact).
if (id.includes('vite/') || id.includes('plugin-vue')) return 'vite'
if (id.includes('hydration/dist')) return 'iles'
const name = userChunks?.(id, api)
if (name) return name
if (id.includes('node_modules')) return vendorPerFramework(chunkForExtension, id, api, cache)
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/iles/src/node/build/islands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { promises as fs } from 'fs'
import { relative, resolve } from 'pathe'
import { build as viteBuild, mergeConfig as mergeViteConfig } from 'vite'
import type { UserConfig as ViteUserConfig, Plugin } from 'vite'
import type { PreRenderedChunk } from 'rollup'
import type { PreRenderedChunk } from 'rolldown'
import IslandsPlugins from '../plugin/plugin'
import type { AppConfig, IslandsByPath } from '../shared'
import { TURBO_SCRIPT_PATH } from '../alias'
Expand Down Expand Up @@ -38,8 +38,8 @@ export async function bundleIslands (config: AppConfig, islandsByPath: IslandsBy
emptyOutDir: false,
outDir: config.outDir,
manifest: true,
minify: 'esbuild',
rollupOptions: {
minify: true,
rolldownOptions: {
input: entryFiles,
output: {
entryFileNames: chunkFileNames,
Expand Down
6 changes: 3 additions & 3 deletions packages/iles/src/node/build/render.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { existsSync } from 'fs'
import { join } from 'pathe'
import { renderSSRHead } from '@unhead/ssr'
import type { RollupOutput } from 'rollup'
import type { RolldownOutput } from 'rolldown'
import { renderers } from '@islands/prerender'
import { IslandDefinition } from 'iles'
import { renderToString } from 'vue/server-renderer'
Expand Down Expand Up @@ -39,7 +39,7 @@ export async function renderPages (
export async function renderPage (
config: AppConfig,
islandsByPath: IslandsByPath,
clientChunks: RollupOutput['output'],
clientChunks: RolldownOutput['output'],
route: RouteToRender,
createApp: CreateAppFactory,
) {
Expand Down Expand Up @@ -68,7 +68,7 @@ export async function renderPage (
</html>`
}

function stylesheetTagsFrom (config: AppConfig, clientChunks: RollupOutput['output']) {
function stylesheetTagsFrom (config: AppConfig, clientChunks: RolldownOutput['output']) {
return clientChunks
.filter(chunk => chunk.type === 'asset' && chunk.fileName.endsWith('.css'))
.map(chunk => `<link rel="stylesheet" href="${config.base}${chunk.fileName}">`)
Expand Down
21 changes: 10 additions & 11 deletions packages/iles/src/node/plugin/documents.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { resolve } from 'path'
import { Plugin, ViteDevServer } from 'vite'

import glob from 'fast-glob'
Expand Down Expand Up @@ -112,12 +111,6 @@ export default function documentsPlugin (config: AppConfig): Plugin {
`
},
async transform (code, id) {
// Ensure Vite keeps track of files with the documents pattern that are added or removed.
if (server && id.startsWith(DOCS_VIRTUAL_ID)) {
(server as any)._importGlobMap.set(id, [resolve(root, modulesById[id].pattern)])
return
}

// Replace each usage of useDocuments with an import of a virtual module.
if (fileCanUseDocuments.test(id) && !definitionRegex.test(code)) {
const paths: [string, string][] = []
Expand All @@ -135,13 +128,19 @@ export default function documentsPlugin (config: AppConfig): Plugin {
}
}
},
handleHotUpdate (ctx) {
const file = relative(root, ctx.file)
hotUpdate ({ file, modules }) {
const relFile = relative(root, file)
const extra: typeof modules = []

// Ensure Vite keeps track of files with the documents pattern that are added or removed.
for (const id in modulesById) {
if (modulesById[id].hasDocument(file))
ctx.modules.push(server.moduleGraph.getModuleById(id)!)
if (modulesById[id].hasDocument(relFile)) {
const mod = this.environment.moduleGraph.getModuleById(id)
if (mod) extra.push(mod)
}
}

if (extra.length) return [...modules, ...extra]
},
}
}
Loading
Loading