diff --git a/.changeset/neat-seas-peel.md b/.changeset/neat-seas-peel.md new file mode 100644 index 000000000000..71ce868ccd15 --- /dev/null +++ b/.changeset/neat-seas-peel.md @@ -0,0 +1,23 @@ +--- +'astro': patch +--- + +Allow TypeScript inside script tags + +This makes it so that you can use TypeScript inside of script tags like so: + +```html + +``` + +Note that the the VSCode extension does not currently support this, however. diff --git a/.changeset/spotty-rockets-grow.md b/.changeset/spotty-rockets-grow.md new file mode 100644 index 000000000000..68d4554322b2 --- /dev/null +++ b/.changeset/spotty-rockets-grow.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Allow specifying entryFileNames for client JS diff --git a/.eslintignore b/.eslintignore index c2d3e84009d9..28768c1b90dd 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,8 +1,9 @@ -**/*.js -**/*.ts -!packages/astro/**/*.js -!packages/astro/**/*.ts -packages/astro/test/**/*.js +**/*.d.ts +packages/**/dist/**/* +packages/**/fixtures/**/* +packages/webapi/**/* packages/astro/vendor/vite/**/* +examples/**/* +scripts/**/* .github .changeset diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d2d00d0816d6..28ddba1e69e4 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,7 +1,7 @@ module.exports = { parser: '@typescript-eslint/parser', extends: ['plugin:@typescript-eslint/recommended', 'prettier'], - plugins: ['@typescript-eslint', 'prettier'], + plugins: ['@typescript-eslint', 'prettier', 'no-only-tests'], rules: { '@typescript-eslint/ban-ts-comment': 'off', '@typescript-eslint/camelcase': 'off', @@ -17,5 +17,6 @@ module.exports = { 'prefer-const': 'off', 'no-shadow': 'off', '@typescript-eslint/no-shadow': ['error'], + 'no-only-tests/no-only-tests': 'error', }, }; diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e79d6422f9ea..18e0d03cc426 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,9 +54,6 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: eslint: true - eslint_args: --ignore-pattern test --ignore-pattern vendor - eslint_dir: packages/astro - eslint_extensions: ts prettier: false auto_fix: true git_name: github-actions[bot] diff --git a/examples/basics/package.json b/examples/basics/package.json index 4e8cc05087c4..68ffeb727c38 100644 --- a/examples/basics/package.json +++ b/examples/basics/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/blog-multiple-authors/package.json b/examples/blog-multiple-authors/package.json index 35c2df53e7c5..3d84620a40d8 100644 --- a/examples/blog-multiple-authors/package.json +++ b/examples/blog-multiple-authors/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/preact": "^0.1.3", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "sass": "^1.52.2" }, "dependencies": { diff --git a/examples/blog/package.json b/examples/blog/package.json index 41dcdfbad6df..65855a94b283 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/preact": "^0.1.3", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "preact": "^10.7.3" diff --git a/examples/component/demo/package.json b/examples/component/demo/package.json index 5ef7701b4746..acd46723b5c9 100644 --- a/examples/component/demo/package.json +++ b/examples/component/demo/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@example/my-component": "workspace:*", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/component/package.json b/examples/component/package.json index 17c10aeeb8f5..6ac119aed8ab 100644 --- a/examples/component/package.json +++ b/examples/component/package.json @@ -8,6 +8,6 @@ "serve": "astro --root demo preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/docs/package.json b/examples/docs/package.json index ad9bdd210d08..c88176f08691 100644 --- a/examples/docs/package.json +++ b/examples/docs/package.json @@ -20,6 +20,6 @@ "devDependencies": { "@astrojs/preact": "^0.1.3", "@astrojs/react": "^0.1.3", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/env-vars/package.json b/examples/env-vars/package.json index d76638ecc41b..4895561bfc7e 100644 --- a/examples/env-vars/package.json +++ b/examples/env-vars/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/framework-alpine/package.json b/examples/framework-alpine/package.json index 388360520edc..98f5af1c2b26 100644 --- a/examples/framework-alpine/package.json +++ b/examples/framework-alpine/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "alpinejs": "^3.10.2" diff --git a/examples/framework-lit/package.json b/examples/framework-lit/package.json index a5c28a9c3288..28213a6407e2 100644 --- a/examples/framework-lit/package.json +++ b/examples/framework-lit/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/lit": "^0.2.0", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "@webcomponents/template-shadowroot": "^0.1.0", diff --git a/examples/framework-multiple/package.json b/examples/framework-multiple/package.json index 989ee165180d..a9aa168a7d53 100644 --- a/examples/framework-multiple/package.json +++ b/examples/framework-multiple/package.json @@ -15,7 +15,7 @@ "@astrojs/solid-js": "^0.1.4", "@astrojs/svelte": "^0.1.4", "@astrojs/vue": "^0.1.5", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "@webcomponents/template-shadowroot": "^0.1.0", diff --git a/examples/framework-preact/package.json b/examples/framework-preact/package.json index 26ed2fce3203..c090fc12b9cb 100644 --- a/examples/framework-preact/package.json +++ b/examples/framework-preact/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/preact": "^0.1.3", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "preact": "^10.7.3" diff --git a/examples/framework-react/package.json b/examples/framework-react/package.json index 58fa618056ed..a73f01a9befd 100644 --- a/examples/framework-react/package.json +++ b/examples/framework-react/package.json @@ -12,7 +12,7 @@ "@astrojs/react": "^0.1.3", "@types/react": "^18.0.10", "@types/react-dom": "^18.0.5", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "react": "^18.1.0", diff --git a/examples/framework-solid/package.json b/examples/framework-solid/package.json index 08e5cc448f66..543ccf8c68d1 100644 --- a/examples/framework-solid/package.json +++ b/examples/framework-solid/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/solid-js": "^0.1.4", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "solid-js": "^1.4.3" diff --git a/examples/framework-svelte/package.json b/examples/framework-svelte/package.json index 80178c4280d1..093a5607b7b5 100644 --- a/examples/framework-svelte/package.json +++ b/examples/framework-svelte/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/svelte": "^0.1.4", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "svelte": "^3.48.0" diff --git a/examples/framework-vue/package.json b/examples/framework-vue/package.json index fb6af35e3b31..1ff7355d0c27 100644 --- a/examples/framework-vue/package.json +++ b/examples/framework-vue/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/vue": "^0.1.5", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "vue": "^3.2.36" diff --git a/examples/integrations-playground/package.json b/examples/integrations-playground/package.json index c77c15017c63..922b3b863293 100644 --- a/examples/integrations-playground/package.json +++ b/examples/integrations-playground/package.json @@ -16,7 +16,7 @@ "@astrojs/solid-js": "0.1.4", "@astrojs/tailwind": "^0.2.1", "@astrojs/turbolinks": "^0.1.3", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "solid-js": "^1.4.3" }, "dependencies": { diff --git a/examples/minimal/package.json b/examples/minimal/package.json index 7bdcf3b0d478..08c740c4a730 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/non-html-pages/package.json b/examples/non-html-pages/package.json index ba96053d7425..9d629151524e 100644 --- a/examples/non-html-pages/package.json +++ b/examples/non-html-pages/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index 22e23c5b24e9..8495bb2d3f3c 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/preact": "^0.1.3", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "sass": "^1.52.2" }, "dependencies": { diff --git a/examples/ssr/package.json b/examples/ssr/package.json index 99611b90f432..5ef91c78a069 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -11,7 +11,7 @@ "devDependencies": { "@astrojs/node": "^0.1.2", "@astrojs/svelte": "^0.1.4", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "concurrently": "^7.2.1", "lightcookie": "^1.0.25", "unocss": "^0.15.6", diff --git a/examples/starter/package.json b/examples/starter/package.json index f151c055246a..ebd0b9915df4 100644 --- a/examples/starter/package.json +++ b/examples/starter/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/subpath/package.json b/examples/subpath/package.json index 5bba82a0b471..cb5c5f505893 100644 --- a/examples/subpath/package.json +++ b/examples/subpath/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/react": "^0.1.3", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "sass": "^1.52.2" }, "dependencies": { diff --git a/examples/with-markdown-plugins/package.json b/examples/with-markdown-plugins/package.json index c1611a063b9f..6c997e4f3d05 100644 --- a/examples/with-markdown-plugins/package.json +++ b/examples/with-markdown-plugins/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/markdown-remark": "^0.11.3", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "hast-util-select": "5.0.1", "rehype-autolink-headings": "^6.1.1", "rehype-slug": "^5.0.1", diff --git a/examples/with-markdown-shiki/package.json b/examples/with-markdown-shiki/package.json index 365e7dbb593f..683b49c76be4 100644 --- a/examples/with-markdown-shiki/package.json +++ b/examples/with-markdown-shiki/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/markdown-remark": "^0.11.3", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/with-markdown/package.json b/examples/with-markdown/package.json index 57ed61765aba..c59c4f1eae4a 100644 --- a/examples/with-markdown/package.json +++ b/examples/with-markdown/package.json @@ -14,7 +14,7 @@ "@astrojs/react": "^0.1.3", "@astrojs/svelte": "^0.1.4", "@astrojs/vue": "^0.1.5", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" }, "dependencies": { "preact": "^10.7.3", diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json index 1519c99e97c9..5a9eba65fabe 100644 --- a/examples/with-nanostores/package.json +++ b/examples/with-nanostores/package.json @@ -25,6 +25,6 @@ "@astrojs/solid-js": "^0.1.4", "@astrojs/svelte": "^0.1.4", "@astrojs/vue": "^0.1.5", - "astro": "^1.0.0-beta.51" + "astro": "^1.0.0-beta.52" } } diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index 2571ddd30462..b579cce2d5da 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/tailwind": "^0.2.1", - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "autoprefixer": "^10.4.7", "canvas-confetti": "^1.5.1", "postcss": "^8.4.14", diff --git a/examples/with-vite-plugin-pwa/package.json b/examples/with-vite-plugin-pwa/package.json index 0e29982613c7..dac62f41891e 100644 --- a/examples/with-vite-plugin-pwa/package.json +++ b/examples/with-vite-plugin-pwa/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^1.0.0-beta.51", + "astro": "^1.0.0-beta.52", "vite-plugin-pwa": "0.11.11", "workbox-window": "^6.5.3" } diff --git a/package.json b/package.json index 3be9d8e87c05..fa8f13392a08 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "test:e2e": "cd packages/astro && pnpm playwright install && pnpm run test:e2e", "test:e2e:match": "cd packages/astro && pnpm playwright install && pnpm run test:e2e:match", "benchmark": "turbo run benchmark --scope=astro", - "lint": "eslint \"packages/**/*.ts\"", + "lint": "eslint .", "version": "changeset version && pnpm install --no-frozen-lockfile && pnpm run format" }, "workspaces": [ @@ -69,6 +69,7 @@ "esbuild": "^0.14.42", "eslint": "^8.16.0", "eslint-config-prettier": "^8.5.0", + "eslint-plugin-no-only-tests": "^2.6.0", "eslint-plugin-prettier": "^4.0.0", "execa": "^6.1.0", "organize-imports-cli": "^0.10.0", diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md index 7782db1560e6..a164694eccc1 100644 --- a/packages/astro/CHANGELOG.md +++ b/packages/astro/CHANGELOG.md @@ -1,5 +1,17 @@ # astro +## 1.0.0-beta.52 + +### Patch Changes + +- [#3667](https://github.com/withastro/astro/pull/3667) [`df02fad1`](https://github.com/withastro/astro/commit/df02fad13ef7c8a8a563ee3720513d437090ee2e) Thanks [@bholmesdev](https://github.com/bholmesdev)! - Fix: add @nanostores/preact to ALWAYS_NOEXTERNAL list for easier onboarding + +* [#3678](https://github.com/withastro/astro/pull/3678) [`89884540`](https://github.com/withastro/astro/commit/898845402cd82995bd4878c93d3ccfcce89ebf27) Thanks [@matthewp](https://github.com/matthewp)! - Fix regression with SSRManifest and client assets + +- [#3658](https://github.com/withastro/astro/pull/3658) [`aeab8909`](https://github.com/withastro/astro/commit/aeab890971e5f425f877545c674d1cb532cee754) Thanks [@matthewp](https://github.com/matthewp)! - Inlines small hoisted scripts + + This enables a perf improvement, whereby small hoisted scripts without dependencies are inlined into the HTML, rather than loaded externally. This uses `vite.build.assetInlineLimit` to determine if the script should be inlined. + ## 1.0.0-beta.51 ### Patch Changes diff --git a/packages/astro/e2e/ts-resolution.test.js b/packages/astro/e2e/ts-resolution.test.js index b1d1fcef6241..b8d8cf9f9d81 100644 --- a/packages/astro/e2e/ts-resolution.test.js +++ b/packages/astro/e2e/ts-resolution.test.js @@ -8,8 +8,8 @@ const test = base.extend({ }, }); -function runTest(test) { - test('client:idle', async ({ page, astro }) => { +function runTest(it) { + it('client:idle', async ({ page, astro }) => { await page.goto(astro.resolveUrl('/')); const counter = page.locator('#client-idle'); diff --git a/packages/astro/package.json b/packages/astro/package.json index a9818e13d2da..97eb6a648303 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "astro", - "version": "1.0.0-beta.51", + "version": "1.0.0-beta.52", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "type": "module", "author": "withastro", diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 81cfe106a06a..36fb01ff2029 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -3,6 +3,7 @@ import type { EndpointHandler, ManifestData, RouteData, + SSRElement, } from '../../@types/astro'; import type { LogOptions } from '../logger/core.js'; import type { RouteInfo, SSRManifest as Manifest } from './types'; @@ -15,7 +16,7 @@ import { render } from '../render/core.js'; import { RouteCache } from '../render/route-cache.js'; import { createLinkStylesheetElementSet, - createModuleScriptElementWithSrcSet, + createModuleScriptElement, } from '../render/ssr-element.js'; import { matchRoute } from '../routing/match.js'; export { deserializeManifest } from './common.js'; @@ -79,18 +80,17 @@ export class App { const info = this.#routeDataToRouteInfo.get(routeData!)!; const links = createLinkStylesheetElementSet(info.links, manifest.site); - const filteredScripts = info.scripts.filter( - (script) => typeof script === 'string' || script?.stage !== 'head-inline' - ) as string[]; - const scripts = createModuleScriptElementWithSrcSet(filteredScripts, manifest.site); - - // Add all injected scripts to the page. + let scripts = new Set(); for (const script of info.scripts) { - if (typeof script !== 'string' && script.stage === 'head-inline') { - scripts.add({ - props: {}, - children: script.children, - }); + if ('stage' in script) { + if (script.stage === 'head-inline') { + scripts.add({ + props: {}, + children: script.children, + }); + } + } else { + scripts.add(createModuleScriptElement(script, manifest.site)); } } diff --git a/packages/astro/src/core/app/types.ts b/packages/astro/src/core/app/types.ts index 7410ad42aa87..09f0a79d2fca 100644 --- a/packages/astro/src/core/app/types.ts +++ b/packages/astro/src/core/app/types.ts @@ -12,7 +12,12 @@ export interface RouteInfo { routeData: RouteData; file: string; links: string[]; - scripts: Array; + scripts: // Integration injected + ( + | { children: string; stage: string } + // Hoisted + | { type: 'inline' | 'external'; value: string } + )[]; } export type SerializedRouteInfo = Omit & { diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 37abb91ad0dd..05d1bcc55e43 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -16,10 +16,7 @@ import { BEFORE_HYDRATION_SCRIPT_ID } from '../../vite-plugin-scripts/index.js'; import { call as callEndpoint } from '../endpoint/index.js'; import { debug, info } from '../logger/core.js'; import { render } from '../render/core.js'; -import { - createLinkStylesheetElementSet, - createModuleScriptElementWithSrcSet, -} from '../render/ssr-element.js'; +import { createLinkStylesheetElementSet, createModuleScriptsSet } from '../render/ssr-element.js'; import { createRequest } from '../request.js'; import { getOutputFilename, isBuildingToSSR } from '../util.js'; import { getOutFile, getOutFolder } from './common.js'; @@ -124,7 +121,7 @@ async function generatePage( const pageInfo = getPageDataByComponent(internals, pageData.route.component); const linkIds: string[] = Array.from(pageInfo?.css ?? []); - const hoistedId = pageInfo?.hoistedScript ?? null; + const scripts = pageInfo?.hoistedScript ?? null; const pageModule = ssrEntry.pageMap.get(pageData.component); @@ -143,7 +140,7 @@ async function generatePage( pageData, internals, linkIds, - hoistedId, + scripts, mod: pageModule, renderers, }; @@ -167,7 +164,7 @@ interface GeneratePathOptions { pageData: PageBuildData; internals: BuildInternals; linkIds: string[]; - hoistedId: string | null; + scripts: { type: 'inline' | 'external'; value: string } | null; mod: ComponentInstance; renderers: SSRLoadedRenderer[]; } @@ -182,7 +179,7 @@ async function generatePath( gopts: GeneratePathOptions ) { const { astroConfig, logging, origin, routeCache } = opts; - const { mod, internals, linkIds, hoistedId, pageData, renderers } = gopts; + const { mod, internals, linkIds, scripts: hoistedScripts, pageData, renderers } = gopts; // This adds the page name to the array so it can be shown as part of stats. if (pageData.route.type === 'page') { @@ -198,7 +195,7 @@ async function generatePath( ? joinPaths(astroConfig.site?.toString() || 'http://localhost/', astroConfig.base) : astroConfig.site; const links = createLinkStylesheetElementSet(linkIds.reverse(), site); - const scripts = createModuleScriptElementWithSrcSet(hoistedId ? [hoistedId] : [], site); + const scripts = createModuleScriptsSet(hoistedScripts ? [hoistedScripts] : [], site); // Add all injected scripts to the page. for (const script of astroConfig._ctx.scripts) { diff --git a/packages/astro/src/core/build/page-data.ts b/packages/astro/src/core/build/page-data.ts index 232278346fd3..fc8be5eab747 100644 --- a/packages/astro/src/core/build/page-data.ts +++ b/packages/astro/src/core/build/page-data.ts @@ -69,7 +69,6 @@ export async function collectPagesData( moduleSpecifier: '', css: new Set(), hoistedScript: undefined, - scripts: new Set(), }; clearInterval(routeCollectionLogTimeout); @@ -131,7 +130,6 @@ export async function collectPagesData( moduleSpecifier: '', css: new Set(), hoistedScript: undefined, - scripts: new Set(), }; } diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index cbce7ab14ee7..25e0b04e4120 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -116,10 +116,10 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp input: [], output: { format: 'esm', - entryFileNames: opts.buildConfig.serverEntry, - chunkFileNames: 'chunks/chunk.[hash].mjs', - assetFileNames: 'assets/asset.[hash][extname]', + chunkFileNames: 'chunks/[name].[hash].mjs', + assetFileNames: 'assets/[name].[hash][extname]', ...viteConfig.build?.rollupOptions?.output, + entryFileNames: opts.buildConfig.serverEntry, }, }, ssr: true, @@ -202,9 +202,9 @@ async function clientBuild( input: Array.from(input), output: { format: 'esm', - entryFileNames: 'entry.[hash].js', - chunkFileNames: 'chunks/chunk.[hash].js', - assetFileNames: 'assets/asset.[hash][extname]', + entryFileNames: '[name].[hash].js', + chunkFileNames: 'chunks/[name].[hash].js', + assetFileNames: 'assets/[name].[hash][extname]', ...viteConfig.build?.rollupOptions?.output, }, preserveEntrySignatures: 'exports-only', diff --git a/packages/astro/src/core/build/types.ts b/packages/astro/src/core/build/types.ts index 0d018be7d4b6..4b734fb9ea0a 100644 --- a/packages/astro/src/core/build/types.ts +++ b/packages/astro/src/core/build/types.ts @@ -19,8 +19,7 @@ export interface PageBuildData { route: RouteData; moduleSpecifier: string; css: Set; - hoistedScript: string | undefined; - scripts: Set; + hoistedScript: { type: 'inline' | 'external'; value: string } | undefined; } export type AllPagesData = Record; diff --git a/packages/astro/src/core/build/vite-plugin-analyzer.ts b/packages/astro/src/core/build/vite-plugin-analyzer.ts index 04b439b6976f..8b9950ff182e 100644 --- a/packages/astro/src/core/build/vite-plugin-analyzer.ts +++ b/packages/astro/src/core/build/vite-plugin-analyzer.ts @@ -21,7 +21,7 @@ export function vitePluginAnalyzer( scan(this: PluginContext, scripts: AstroPluginMetadata['astro']['scripts'], from: string) { const hoistedScripts = new Set(); for (let i = 0; i < scripts.length; i++) { - const hid = `${from.replace('/@fs', '')}?astro&type=script&index=${i}`; + const hid = `${from.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`; hoistedScripts.add(hid); } diff --git a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts index 0ac874fba136..9ab7ece453dd 100644 --- a/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts +++ b/packages/astro/src/core/build/vite-plugin-hoisted-scripts.ts @@ -40,6 +40,8 @@ export function vitePluginHoistedScripts( }, async generateBundle(_options, bundle) { + let assetInlineLimit = astroConfig.vite?.build?.assetsInlineLimit || 4096; + // Find all page entry points and create a map of the entry point to the hashed hoisted script. // This is used when we render so that we can add the script to the head. for (const [id, output] of Object.entries(bundle)) { @@ -48,15 +50,36 @@ export function vitePluginHoistedScripts( output.facadeModuleId && virtualHoistedEntry(output.facadeModuleId) ) { + const canBeInlined = + output.imports.length === 0 && + output.dynamicImports.length === 0 && + Buffer.byteLength(output.code) <= assetInlineLimit; + let removeFromBundle = false; const facadeId = output.facadeModuleId!; const pages = internals.hoistedScriptIdToPagesMap.get(facadeId)!; for (const pathname of pages) { const vid = viteID(new URL('.' + pathname, astroConfig.root)); const pageInfo = getPageDataByViteID(internals, vid); if (pageInfo) { - pageInfo.hoistedScript = id; + if (canBeInlined) { + pageInfo.hoistedScript = { + type: 'inline', + value: output.code, + }; + removeFromBundle = true; + } else { + pageInfo.hoistedScript = { + type: 'external', + value: id, + }; + } } } + + // Remove the bundle if it was inlined + if (removeFromBundle) { + delete bundle[id]; + } } } }, diff --git a/packages/astro/src/core/build/vite-plugin-ssr.ts b/packages/astro/src/core/build/vite-plugin-ssr.ts index e543e925ed2a..05ff80916fb9 100644 --- a/packages/astro/src/core/build/vite-plugin-ssr.ts +++ b/packages/astro/src/core/build/vite-plugin-ssr.ts @@ -70,12 +70,6 @@ if(_start in adapter) { return void 0; }, async generateBundle(_opts, bundle) { - internals.staticFiles = new Set( - await glob('**/*', { - cwd: fileURLToPath(buildOpts.buildConfig.client), - }) - ); - // Add assets from this SSR chunk as well. for (const [_chunkName, chunk] of Object.entries(bundle)) { if (chunk.type === 'asset') { @@ -101,6 +95,16 @@ export async function injectManifest(buildOpts: StaticBuildOptions, internals: B throw new Error(`Did not generate an entry chunk for SSR`); } + // Add assets from the client build. + const clientStatics = new Set( + await glob('**/*', { + cwd: fileURLToPath(buildOpts.buildConfig.client), + }) + ); + for (const file of clientStatics) { + internals.staticFiles.add(file); + } + const staticFiles = internals.staticFiles; const manifest = buildManifest(buildOpts, internals, Array.from(staticFiles)); await runHookBuildSsr({ config: buildOpts.astroConfig, manifest }); @@ -125,7 +129,7 @@ function buildManifest( const routes: SerializedRouteInfo[] = []; for (const pageData of eachPageData(internals)) { - const scripts = Array.from(pageData.scripts); + const scripts: SerializedRouteInfo['scripts'] = []; if (pageData.hoistedScript) { scripts.unshift(pageData.hoistedScript); } diff --git a/packages/astro/src/core/create-vite.ts b/packages/astro/src/core/create-vite.ts index 7c447aadfaf3..d0fd6f3a6e98 100644 --- a/packages/astro/src/core/create-vite.ts +++ b/packages/astro/src/core/create-vite.ts @@ -28,7 +28,11 @@ const ALWAYS_EXTERNAL = new Set([ 'whatwg-url', ]); const ALWAYS_NOEXTERNAL = new Set([ - 'astro', // This is only because Vite's native ESM doesn't resolve "exports" correctly. + // This is only because Vite's native ESM doesn't resolve "exports" correctly. + 'astro', + // Handle recommended nanostores. Only @nanostores/preact is required from our testing! + // Full explanation and related bug report: https://github.com/withastro/astro/pull/3667 + '@nanostores/preact', ]); // note: ssr is still an experimental API hence the type omission from `vite` diff --git a/packages/astro/src/core/render/ssr-element.ts b/packages/astro/src/core/render/ssr-element.ts index 628294f44a38..4828583ee25e 100644 --- a/packages/astro/src/core/render/ssr-element.ts +++ b/packages/astro/src/core/render/ssr-element.ts @@ -25,6 +25,22 @@ export function createLinkStylesheetElementSet(hrefs: string[], site?: string) { return new Set(hrefs.map((href) => createLinkStylesheetElement(href, site))); } +export function createModuleScriptElement( + script: { type: 'inline' | 'external'; value: string }, + site?: string +): SSRElement { + if (script.type === 'external') { + return createModuleScriptElementWithSrc(script.value, site); + } else { + return { + props: { + type: 'module', + }, + children: script.value, + }; + } +} + export function createModuleScriptElementWithSrc(src: string, site?: string): SSRElement { return { props: { @@ -41,3 +57,10 @@ export function createModuleScriptElementWithSrcSet( ): Set { return new Set(srces.map((src) => createModuleScriptElementWithSrc(src, site))); } + +export function createModuleScriptsSet( + scripts: { type: 'inline' | 'external'; value: string }[], + site?: string +): Set { + return new Set(scripts.map((script) => createModuleScriptElement(script, site))); +} diff --git a/packages/astro/src/runtime/server/metadata.ts b/packages/astro/src/runtime/server/metadata.ts index c736820d233f..3093ee7f11ae 100644 --- a/packages/astro/src/runtime/server/metadata.ts +++ b/packages/astro/src/runtime/server/metadata.ts @@ -65,7 +65,7 @@ export class Metadata { while (i < metadata.hoisted.length) { // Strip off the leading "/@fs" added during compilation. - yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}`; + yield `${pathname.replace('/@fs', '')}?astro&type=script&index=${i}&lang.ts`; i++; } } diff --git a/packages/astro/src/vite-plugin-astro/index.ts b/packages/astro/src/vite-plugin-astro/index.ts index 94fea7c89f3a..1318d7458623 100644 --- a/packages/astro/src/vite-plugin-astro/index.ts +++ b/packages/astro/src/vite-plugin-astro/index.ts @@ -15,7 +15,7 @@ import { PAGE_SCRIPT_ID, PAGE_SSR_SCRIPT_ID } from '../vite-plugin-scripts/index import { getFileInfo } from '../vite-plugin-utils/index.js'; import { cachedCompilation, CompileProps } from './compile.js'; import { handleHotUpdate, trackCSSDependencies } from './hmr.js'; -import { parseAstroRequest } from './query.js'; +import { parseAstroRequest, ParsedRequestResult } from './query.js'; import { getViteTransform, TransformHook } from './styles.js'; const FRONTMATTER_PARSE_REGEXP = /^\-\-\-(.*)^\-\-\-/ms; @@ -48,6 +48,16 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu const srcRootWeb = config.srcDir.pathname.slice(config.root.pathname.length - 1); const isBrowserPath = (path: string) => path.startsWith(srcRootWeb); + function resolveRelativeFromAstroParent(id: string, parsedFrom: ParsedRequestResult): string { + const filename = normalizeFilename(parsedFrom.filename); + const resolvedURL = new URL(id, `file://${filename}`); + const resolved = resolvedURL.pathname; + if (isBrowserPath(resolved)) { + return relativeToRoot(resolved + resolvedURL.search); + } + return slash(fileURLToPath(resolvedURL)) + resolvedURL.search; + } + return { name: 'astro:build', enforce: 'pre', // run transforms before other plugins can @@ -59,19 +69,17 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu viteDevServer = server; }, // note: don’t claim .astro files with resolveId() — it prevents Vite from transpiling the final JS (import.meta.globEager, etc.) - async resolveId(id, from) { + async resolveId(id, from, opts) { // If resolving from an astro subresource such as a hoisted script, // we need to resolve relative paths ourselves. if (from) { const parsedFrom = parseAstroRequest(from); - if (parsedFrom.query.astro && isRelativePath(id) && parsedFrom.query.type === 'script') { - const filename = normalizeFilename(parsedFrom.filename); - const resolvedURL = new URL(id, `file://${filename}`); - const resolved = resolvedURL.pathname; - if (isBrowserPath(resolved)) { - return relativeToRoot(resolved + resolvedURL.search); - } - return slash(fileURLToPath(resolvedURL)) + resolvedURL.search; + const isAstroScript = parsedFrom.query.astro && parsedFrom.query.type === 'script'; + if (isAstroScript && isRelativePath(id)) { + return this.resolve(resolveRelativeFromAstroParent(id, parsedFrom), from, { + custom: opts.custom, + skipSelf: true, + }); } } @@ -170,6 +178,11 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu hoistedScript.type === 'inline' ? hoistedScript.code! : `import "${hoistedScript.src!}";`, + meta: { + vite: { + lang: 'ts', + }, + }, }; } } @@ -205,8 +218,8 @@ export default function astro({ config, logging }: AstroPluginOptions): vite.Plu let i = 0; while (i < transformResult.scripts.length) { - deps.add(`${id}?astro&type=script&index=${i}`); - SUFFIX += `import "${id}?astro&type=script&index=${i}";`; + deps.add(`${id}?astro&type=script&index=${i}&lang.ts`); + SUFFIX += `import "${id}?astro&type=script&index=${i}&lang.ts";`; i++; } diff --git a/packages/astro/src/vite-plugin-astro/query.ts b/packages/astro/src/vite-plugin-astro/query.ts index ae923c153639..bc4908bbe19b 100644 --- a/packages/astro/src/vite-plugin-astro/query.ts +++ b/packages/astro/src/vite-plugin-astro/query.ts @@ -7,13 +7,15 @@ export interface AstroQuery { raw?: boolean; } +export interface ParsedRequestResult { + filename: string; + query: AstroQuery; +} + // Parses an id to check if its an Astro request. // CSS is imported like `import '/src/pages/index.astro?astro&type=style&index=0&lang.css'; // This parses those ids and returns an object representing what it found. -export function parseAstroRequest(id: string): { - filename: string; - query: AstroQuery; -} { +export function parseAstroRequest(id: string): ParsedRequestResult { const [filename, rawQuery] = id.split(`?`, 2); const query = Object.fromEntries(new URLSearchParams(rawQuery).entries()) as AstroQuery; if (query.astro != null) { diff --git a/packages/astro/test/astro-css-bundling.test.js b/packages/astro/test/astro-css-bundling.test.js index 3170b796d068..1c470c0ef55b 100644 --- a/packages/astro/test/astro-css-bundling.test.js +++ b/packages/astro/test/astro-css-bundling.test.js @@ -52,8 +52,8 @@ describe('CSS Bundling', function () { // test 3: assert all bundled CSS was built and contains CSS for (const url of builtCSS.keys()) { - const css = await fixture.readFile(url); - expect(css).to.be.ok; + const bundledCss = await fixture.readFile(url); + expect(bundledCss).to.be.ok; } } }); diff --git a/packages/astro/test/astro-dynamic.test.js b/packages/astro/test/astro-dynamic.test.js index 5fcc4596c14b..6f3c321984af 100644 --- a/packages/astro/test/astro-dynamic.test.js +++ b/packages/astro/test/astro-dynamic.test.js @@ -36,7 +36,7 @@ describe('Dynamic components', () => { expect($('astro-island').html()).to.equal(''); // test 2: component url const href = $('astro-island').attr('component-url'); - expect(href).to.include(`/entry`); + expect(href).to.include(`/PersistentCounter`); }); }); @@ -75,6 +75,6 @@ describe('Dynamic components subpath', () => { expect($('astro-island').html()).to.equal(''); // test 2: has component url const attr = $('astro-island').attr('component-url'); - expect(attr).to.include(`blog/entry`); + expect(attr).to.include(`blog/PersistentCounter`); }); }); diff --git a/packages/astro/test/astro-scripts.test.js b/packages/astro/test/astro-scripts.test.js index 90dba2997008..dac6a18c747d 100644 --- a/packages/astro/test/astro-scripts.test.js +++ b/packages/astro/test/astro-scripts.test.js @@ -37,15 +37,16 @@ describe('Scripts (hoisted and not)', () => { // Inline page let inline = await fixture.readFile('/inline/index.html'); let $ = cheerio.load(inline); + let $el = $('script'); // test 1: Just one entry module - expect($('script')).to.have.lengthOf(1); + expect($el).to.have.lengthOf(1); // test 2: attr removed - expect($('script').attr('data-astro')).to.equal(undefined); + expect($el.attr('data-astro')).to.equal(undefined); - const entryURL = $('script').attr('src'); - const inlineEntryJS = await fixture.readFile(entryURL); + expect($el.attr('src')).to.equal(undefined); + const inlineEntryJS = $el.text(); // test 3: the JS exists expect(inlineEntryJS).to.be.ok; @@ -57,6 +58,14 @@ describe('Scripts (hoisted and not)', () => { ); }); + it("Inline scripts that are shared by multiple pages create chunks, and aren't inlined into the HTML", async () => { + let html = await fixture.readFile('/inline-shared-one/index.html'); + let $ = cheerio.load(html); + + expect($('script')).to.have.lengthOf(1); + expect($('script').attr('src')).to.not.equal(undefined); + }); + it('External page builds the hoisted scripts to a single bundle', async () => { let external = await fixture.readFile('/external/index.html'); let $ = cheerio.load(external); @@ -65,8 +74,8 @@ describe('Scripts (hoisted and not)', () => { expect($('script')).to.have.lengthOf(2); let el = $('script').get(1); - let entryURL = $(el).attr('src'); - let externalEntryJS = await fixture.readFile(entryURL); + expect($(el).attr('src')).to.equal(undefined, 'This should have been inlined'); + let externalEntryJS = $(el).text(); // test 2: the JS exists expect(externalEntryJS).to.be.ok; diff --git a/packages/astro/test/entry-file-names.test.js b/packages/astro/test/entry-file-names.test.js new file mode 100644 index 000000000000..71f93876a216 --- /dev/null +++ b/packages/astro/test/entry-file-names.test.js @@ -0,0 +1,26 @@ +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('vite.build.rollupOptions.entryFileNames', () => { + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/entry-file-names', + }); + await fixture.build(); + }); + + it('Renders correctly', async () => { + const html = await fixture.readFile('/index.html'); + const $ = cheerio.load(html); + expect($('#hello')).to.have.a.lengthOf(1); + }); + + it('Outputs a client module that was specified by the config', async () => { + const js = await fixture.readFile('/assets/js/Hello.js'); + expect(js).to.be.a('string'); + expect(js.length).to.be.greaterThan(0); + }); +}); diff --git a/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro b/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro index dfe895d6ce83..13c64eb37d7f 100644 --- a/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro +++ b/packages/astro/test/fixtures/astro-scripts/src/components/Inline.astro @@ -1,3 +1,11 @@ diff --git a/packages/astro/test/fixtures/astro-scripts/src/components/InlineShared.astro b/packages/astro/test/fixtures/astro-scripts/src/components/InlineShared.astro new file mode 100644 index 000000000000..2be6f7d7fa6a --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/components/InlineShared.astro @@ -0,0 +1,3 @@ + diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-one.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-one.astro new file mode 100644 index 000000000000..a035fa8c7c19 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-one.astro @@ -0,0 +1,14 @@ +--- +import InlineShared from '../components/InlineShared.astro'; +--- + + + Testing + + + + + + diff --git a/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-two.astro b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-two.astro new file mode 100644 index 000000000000..97f7403fcef0 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/pages/inline-shared-two.astro @@ -0,0 +1,14 @@ +--- +import InlineShared from '../components/InlineShared.astro'; +--- + + + Testing + + + + + + diff --git a/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts new file mode 100644 index 000000000000..6125b5a48425 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/one.ts @@ -0,0 +1 @@ +console.log('some-files/one'); diff --git a/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts new file mode 100644 index 000000000000..113f7075f231 --- /dev/null +++ b/packages/astro/test/fixtures/astro-scripts/src/scripts/some-files/two.ts @@ -0,0 +1 @@ +console.log('some-files/two'); diff --git a/packages/astro/test/fixtures/entry-file-names/astro.config.mjs b/packages/astro/test/fixtures/entry-file-names/astro.config.mjs new file mode 100644 index 000000000000..fbca4b567007 --- /dev/null +++ b/packages/astro/test/fixtures/entry-file-names/astro.config.mjs @@ -0,0 +1,16 @@ +import { defineConfig } from 'astro/config'; +import preact from '@astrojs/preact'; + +// https://astro.build/config +export default defineConfig({ + integrations: [preact()], + vite: { + build: { + rollupOptions: { + output: { + entryFileNames: `assets/js/[name].js`, + }, + }, + }, + }, +}); diff --git a/packages/astro/test/fixtures/entry-file-names/package.json b/packages/astro/test/fixtures/entry-file-names/package.json new file mode 100644 index 000000000000..760acaedb9f5 --- /dev/null +++ b/packages/astro/test/fixtures/entry-file-names/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/entry-file-names", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/preact": "workspace:", + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/entry-file-names/src/components/Hello.jsx b/packages/astro/test/fixtures/entry-file-names/src/components/Hello.jsx new file mode 100644 index 000000000000..833f20f8e56f --- /dev/null +++ b/packages/astro/test/fixtures/entry-file-names/src/components/Hello.jsx @@ -0,0 +1,6 @@ + +export default function() { + return ( +
Hello world
+ ) +} diff --git a/packages/astro/test/fixtures/entry-file-names/src/pages/index.astro b/packages/astro/test/fixtures/entry-file-names/src/pages/index.astro new file mode 100644 index 000000000000..aac79cece6b9 --- /dev/null +++ b/packages/astro/test/fixtures/entry-file-names/src/pages/index.astro @@ -0,0 +1,10 @@ +--- +import Hello from '../components/Hello.jsx'; +--- + + + Test + + + + diff --git a/packages/astro/test/fixtures/ssr-scripts/astro.config.mjs b/packages/astro/test/fixtures/ssr-scripts/astro.config.mjs new file mode 100644 index 000000000000..08916b1fea78 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-scripts/astro.config.mjs @@ -0,0 +1,7 @@ +import { defineConfig } from 'astro/config'; +import preact from '@astrojs/preact'; + +// https://astro.build/config +export default defineConfig({ + integrations: [preact()], +}); diff --git a/packages/astro/test/fixtures/ssr-scripts/package.json b/packages/astro/test/fixtures/ssr-scripts/package.json new file mode 100644 index 000000000000..2050dfbec049 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-scripts/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/ssr-scripts", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/preact": "workspace:", + "astro": "workspace:*" + } +} diff --git a/packages/astro/test/fixtures/ssr-scripts/src/components/Hello.jsx b/packages/astro/test/fixtures/ssr-scripts/src/components/Hello.jsx new file mode 100644 index 000000000000..70279a587883 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-scripts/src/components/Hello.jsx @@ -0,0 +1,6 @@ + +export default function() { + return ( +
Hello world
+ ) +} diff --git a/packages/astro/test/fixtures/ssr-scripts/src/pages/index.astro b/packages/astro/test/fixtures/ssr-scripts/src/pages/index.astro new file mode 100644 index 000000000000..8b27cdd3b6ef --- /dev/null +++ b/packages/astro/test/fixtures/ssr-scripts/src/pages/index.astro @@ -0,0 +1,11 @@ +--- +import Hello from '../components/Hello.jsx'; +--- + + + Astro + + + + + diff --git a/packages/astro/test/sass.test.js b/packages/astro/test/sass.test.js index 4072d5547ae9..07c1f1499263 100644 --- a/packages/astro/test/sass.test.js +++ b/packages/astro/test/sass.test.js @@ -20,7 +20,7 @@ describe('Sass', () => { // TODO: Sass cannot be found on macOS for some reason... Vite issue? const test = os.platform() === 'darwin' ? it.skip : it; test('shows helpful error on failure', async () => { - const res = await fixture.fetch('/error').then((res) => res.text()); - expect(res).to.include('Undefined variable'); + const text = await fixture.fetch('/error').then((res) => res.text()); + expect(text).to.include('Undefined variable'); }); }); diff --git a/packages/astro/test/ssr-adapter-build-config.test.js b/packages/astro/test/ssr-adapter-build-config.test.js index bb1c4514a885..1f76d7e6a275 100644 --- a/packages/astro/test/ssr-adapter-build-config.test.js +++ b/packages/astro/test/ssr-adapter-build-config.test.js @@ -26,8 +26,10 @@ describe('Integration buildConfig hook', () => { if (id === '@my-ssr') { return id; } else if (id === 'astro/app') { - const id = viteID(new URL('../dist/core/app/index.js', import.meta.url)); - return id; + const viteId = viteID( + new URL('../dist/core/app/index.js', import.meta.url) + ); + return viteId; } }, load(id) { diff --git a/packages/astro/test/ssr-scripts.test.js b/packages/astro/test/ssr-scripts.test.js new file mode 100644 index 000000000000..f44099e41c27 --- /dev/null +++ b/packages/astro/test/ssr-scripts.test.js @@ -0,0 +1,27 @@ +import { expect } from 'chai'; +import { loadFixture } from './test-utils.js'; +import testAdapter from './test-adapter.js'; + +describe('SSR Hydrated component scripts', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture; + + before(async () => { + fixture = await loadFixture({ + root: './fixtures/ssr-scripts/', + experimental: { + ssr: true, + }, + adapter: testAdapter(), + }); + await fixture.build(); + }); + + it('Are included in the manifest.assets so that an adapter can know to serve static', async () => { + const app = await fixture.loadTestAdapterApp(); + + /** @type {Set} */ + const assets = app.manifest.assets; + expect(assets.size).to.be.greaterThan(0); + }); +}); diff --git a/packages/astro/test/static-build-page-dist-url.test.js b/packages/astro/test/static-build-page-dist-url.test.js index 59adbc57c5de..cf983992665c 100644 --- a/packages/astro/test/static-build-page-dist-url.test.js +++ b/packages/astro/test/static-build-page-dist-url.test.js @@ -2,11 +2,10 @@ import { expect } from 'chai'; import { loadFixture } from './test-utils.js'; describe('Static build: pages routes have distURL', () => { - /** @type {import('./test-utils').Fixture} */ - let fixture; /** @type {RouteData[]} */ let checkRoutes; before(async () => { + /** @type {import('./test-utils').Fixture} */ const fixture = await loadFixture({ root: './fixtures/astro pages/', integrations: [ diff --git a/packages/astro/test/tailwindcss.test.js b/packages/astro/test/tailwindcss.test.js index 15723c456881..7a59aebe5762 100644 --- a/packages/astro/test/tailwindcss.test.js +++ b/packages/astro/test/tailwindcss.test.js @@ -2,8 +2,6 @@ import { expect } from 'chai'; import * as cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; -let fixture; - describe('Tailwind', () => { let fixture; @@ -62,10 +60,10 @@ describe('Tailwind', () => { it('handles Markdown pages', async () => { const html = await fixture.readFile('/markdown-page/index.html'); - const $ = cheerio.load(html); - const bundledCSSHREF = $('link[rel=stylesheet][href^=/assets/]').attr('href'); - const bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); - expect(bundledCSS, 'includes used component classes').to.match(/\.bg-purple-600{/); + const $md = cheerio.load(html); + const bundledCSSHREF = $md('link[rel=stylesheet][href^=/assets/]').attr('href'); + const mdBundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); + expect(mdBundledCSS, 'includes used component classes').to.match(/\.bg-purple-600{/); }); }); }); diff --git a/packages/astro/test/test-adapter.js b/packages/astro/test/test-adapter.js index 99ab34e5df95..0ed8014ce254 100644 --- a/packages/astro/test/test-adapter.js +++ b/packages/astro/test/test-adapter.js @@ -17,8 +17,8 @@ export default function () { if (id === '@my-ssr') { return id; } else if (id === 'astro/app') { - const id = viteID(new URL('../dist/core/app/index.js', import.meta.url)); - return id; + const viteId = viteID(new URL('../dist/core/app/index.js', import.meta.url)); + return viteId; } }, load(id) { diff --git a/packages/create-astro/src/index.ts b/packages/create-astro/src/index.ts index 4fb6cec2839b..08396a4e8246 100644 --- a/packages/create-astro/src/index.ts +++ b/packages/create-astro/src/index.ts @@ -1,3 +1,4 @@ +/* eslint no-console: 'off' */ import degit from 'degit'; import { execa, execaCommand } from 'execa'; import fs from 'fs'; diff --git a/packages/create-astro/test/directory-step.test.js b/packages/create-astro/test/directory-step.test.js index 7193fe298fc2..7c629598ad19 100644 --- a/packages/create-astro/test/directory-step.test.js +++ b/packages/create-astro/test/directory-step.test.js @@ -1,4 +1,4 @@ -import { resolve } from 'path'; +import path from 'path'; import { promises, existsSync } from 'fs'; import { PROMPT_MESSAGES, testDir, setup, promiseWithTimeout, timeout } from './utils.js'; @@ -31,7 +31,7 @@ describe('[create-astro] select directory', function () { }); }); it('should proceed on an empty directory', async function () { - const resolvedEmptyDirPath = resolve(testDir, inputs.emptyDir); + const resolvedEmptyDirPath = path.resolve(testDir, inputs.emptyDir); if (!existsSync(resolvedEmptyDirPath)) { await promises.mkdir(resolvedEmptyDirPath); } diff --git a/packages/integrations/deno/src/server.ts b/packages/integrations/deno/src/server.ts index eb83c8eae7e9..9d2fc98a9c89 100644 --- a/packages/integrations/deno/src/server.ts +++ b/packages/integrations/deno/src/server.ts @@ -45,6 +45,7 @@ export function start(manifest: SSRManifest, options: Options) { }); _startPromise = Promise.resolve(_server.listenAndServe()); + // eslint-disable-next-line no-console console.error(`Server running on port ${port}`); } diff --git a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js b/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js index 2a261b7f670f..82961ab8b90d 100644 --- a/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js +++ b/packages/integrations/netlify/test/edge-functions/dynamic-import.test.js @@ -20,6 +20,7 @@ Deno.test({ const div = doc.querySelector('#thing'); assert(div, 'div exists'); } catch (err) { + // eslint-disable-next-line no-console console.error(err); } finally { await close(); diff --git a/packages/integrations/partytown/src/sirv.ts b/packages/integrations/partytown/src/sirv.ts index aab0c7d96097..78489d2ac52f 100644 --- a/packages/integrations/partytown/src/sirv.ts +++ b/packages/integrations/partytown/src/sirv.ts @@ -200,7 +200,7 @@ export default function (dir, opts = {}) { }); } - let lookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES); + let fileLookup = opts.dev ? viaLocal.bind(0, dir, isEtag) : viaCache.bind(0, FILES); return function (req, res, next) { let extns = ['']; @@ -224,7 +224,8 @@ export default function (dir, opts = {}) { } let data = - lookup(pathname, extns) || (isSPA && !isMatch(pathname, ignores) && lookup(fallback, extns)); + fileLookup(pathname, extns) || + (isSPA && !isMatch(pathname, ignores) && fileLookup(fallback, extns)); if (!data) return next ? next() : isNotFound(req, res); if (isEtag && req.headers['if-none-match'] === data.headers['ETag']) { diff --git a/packages/integrations/sitemap/src/utils/logger.ts b/packages/integrations/sitemap/src/utils/logger.ts index 203baeaa7a57..3292bbdfc6bb 100644 --- a/packages/integrations/sitemap/src/utils/logger.ts +++ b/packages/integrations/sitemap/src/utils/logger.ts @@ -23,7 +23,7 @@ export class Logger implements ILogger { this.packageName = packageName; } - private log(msg: string, prefix: string = '') { + private log(msg: string, prefix = '') { // eslint-disable-next-line no-console console.log(`%s${this.packageName}:%s ${msg}\n`, prefix, prefix ? this.colors.reset : ''); } diff --git a/packages/integrations/sitemap/src/validate-options.ts b/packages/integrations/sitemap/src/validate-options.ts index e4b458003e19..f51750ff51c1 100644 --- a/packages/integrations/sitemap/src/validate-options.ts +++ b/packages/integrations/sitemap/src/validate-options.ts @@ -10,7 +10,7 @@ export const validateOptions = (site: string | undefined, opts: SitemapOptions) site: z.string().optional(), // Astro takes care of `site`: how to validate, transform and refine canonicalURL: z.string().optional(), // `canonicalURL` is already validated in prev step }) - .refine(({ site, canonicalURL }) => site || canonicalURL, { + .refine((options) => options.site || options.canonicalURL, { message: 'Required `site` astro.config option or `canonicalURL` integration option', }) .parse({ diff --git a/packages/integrations/vercel/src/lib/fs.ts b/packages/integrations/vercel/src/lib/fs.ts index e192ba554126..d7a833cd08c1 100644 --- a/packages/integrations/vercel/src/lib/fs.ts +++ b/packages/integrations/vercel/src/lib/fs.ts @@ -1,7 +1,7 @@ import type { PathLike } from 'node:fs'; import * as fs from 'node:fs/promises'; -export async function writeJson(path: PathLike, data: T) { +export async function writeJson(path: PathLike, data: T) { await fs.writeFile(path, JSON.stringify(data), { encoding: 'utf-8' }); } diff --git a/packages/markdown/remark/src/index.ts b/packages/markdown/remark/src/index.ts index 7034564c3c80..567a4414d05f 100644 --- a/packages/markdown/remark/src/index.ts +++ b/packages/markdown/remark/src/index.ts @@ -57,8 +57,8 @@ export async function renderMarkdown( const loadedRemarkPlugins = await Promise.all(loadPlugins(remarkPlugins)); const loadedRehypePlugins = await Promise.all(loadPlugins(rehypePlugins)); - loadedRemarkPlugins.forEach(([plugin, opts]) => { - parser.use([[plugin, opts]]); + loadedRemarkPlugins.forEach(([plugin, pluginOpts]) => { + parser.use([[plugin, pluginOpts]]); }); if (scopedClassName) { @@ -87,8 +87,8 @@ export async function renderMarkdown( ], ]); - loadedRehypePlugins.forEach(([plugin, opts]) => { - parser.use([[plugin, opts]]); + loadedRehypePlugins.forEach(([plugin, pluginOpts]) => { + parser.use([[plugin, pluginOpts]]); }); parser @@ -106,6 +106,7 @@ export async function renderMarkdown( // Ensure that the error message contains the input filename // to make it easier for the user to fix the issue err = prefixError(err, `Failed to parse Markdown file "${input.path}"`); + // eslint-disable-next-line no-console console.error(err); throw err; } diff --git a/packages/markdown/remark/src/rehype-collect-headers.ts b/packages/markdown/remark/src/rehype-collect-headers.ts index 76cb5740ca13..f8cedd0d54c0 100644 --- a/packages/markdown/remark/src/rehype-collect-headers.ts +++ b/packages/markdown/remark/src/rehype-collect-headers.ts @@ -20,7 +20,7 @@ export default function createCollectHeaders() { let text = ''; let isJSX = false; - visit(node, (child, _, parent) => { + visit(node, (child, __, parent) => { if (child.type === 'element' || parent == null) { return; } diff --git a/packages/markdown/remark/src/remark-prism.ts b/packages/markdown/remark/src/remark-prism.ts index caa50f738226..8f1173af0206 100644 --- a/packages/markdown/remark/src/remark-prism.ts +++ b/packages/markdown/remark/src/remark-prism.ts @@ -13,9 +13,9 @@ function runHighlighter(lang: string, code: string) { lang = 'plaintext'; } - const ensureLoaded = (lang: string) => { - if (lang && !Prism.languages[lang]) { - loadLanguages([lang]); + const ensureLoaded = (language: string) => { + if (language && !Prism.languages[language]) { + loadLanguages([language]); } }; @@ -30,6 +30,7 @@ function runHighlighter(lang: string, code: string) { } if (lang && !Prism.languages[lang]) { + // eslint-disable-next-line no-console console.warn(`Unable to load the language: ${lang}`); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cd70524a7164..05c6e0f56d17 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,7 @@ importers: esbuild: ^0.14.42 eslint: ^8.16.0 eslint-config-prettier: ^8.5.0 + eslint-plugin-no-only-tests: ^2.6.0 eslint-plugin-prettier: ^4.0.0 execa: ^6.1.0 organize-imports-cli: ^0.10.0 @@ -35,6 +36,7 @@ importers: esbuild: 0.14.43 eslint: 8.17.0 eslint-config-prettier: 8.5.0_eslint@8.17.0 + eslint-plugin-no-only-tests: 2.6.0 eslint-plugin-prettier: 4.0.0_ucegkljdju7q4zmvwxzqoprf3y execa: 6.1.0 organize-imports-cli: 0.10.0 @@ -47,14 +49,14 @@ importers: examples/basics: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/blog: specifiers: '@astrojs/preact': ^0.1.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 dependencies: preact: 10.7.3 @@ -65,7 +67,7 @@ importers: examples/blog-multiple-authors: specifiers: '@astrojs/preact': ^0.1.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 sass: ^1.52.2 dependencies: @@ -77,14 +79,14 @@ importers: examples/component: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/component/demo: specifiers: '@example/my-component': workspace:* - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: '@example/my-component': link:../packages/my-component astro: link:../../../packages/astro @@ -100,7 +102,7 @@ importers: '@docsearch/css': ^3.1.0 '@docsearch/react': ^3.1.0 '@types/react': ^17.0.45 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 react: ^18.1.0 react-dom: ^18.1.0 @@ -119,14 +121,14 @@ importers: examples/env-vars: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/framework-alpine: specifiers: alpinejs: ^3.10.2 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 dependencies: alpinejs: 3.10.2 devDependencies: @@ -136,7 +138,7 @@ importers: specifiers: '@astrojs/lit': ^0.2.0 '@webcomponents/template-shadowroot': ^0.1.0 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 lit: ^2.2.5 dependencies: '@webcomponents/template-shadowroot': 0.1.0 @@ -154,7 +156,7 @@ importers: '@astrojs/svelte': ^0.1.4 '@astrojs/vue': ^0.1.5 '@webcomponents/template-shadowroot': ^0.1.0 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 lit: ^2.2.5 preact: ^10.7.3 react: ^18.1.0 @@ -183,7 +185,7 @@ importers: examples/framework-preact: specifiers: '@astrojs/preact': ^0.1.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 dependencies: preact: 10.7.3 @@ -196,7 +198,7 @@ importers: '@astrojs/react': ^0.1.3 '@types/react': ^18.0.10 '@types/react-dom': ^18.0.5 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 react: ^18.1.0 react-dom: ^18.1.0 dependencies: @@ -211,7 +213,7 @@ importers: examples/framework-solid: specifiers: '@astrojs/solid-js': ^0.1.4 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 solid-js: ^1.4.3 dependencies: solid-js: 1.4.3 @@ -222,7 +224,7 @@ importers: examples/framework-svelte: specifiers: '@astrojs/svelte': ^0.1.4 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 svelte: ^3.48.0 dependencies: svelte: 3.48.0 @@ -233,7 +235,7 @@ importers: examples/framework-vue: specifiers: '@astrojs/vue': ^0.1.5 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 vue: ^3.2.36 dependencies: vue: 3.2.37 @@ -251,7 +253,7 @@ importers: '@astrojs/tailwind': ^0.2.1 '@astrojs/turbolinks': ^0.1.3 '@webcomponents/template-shadowroot': ^0.1.0 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 lit: ^2.2.5 preact: ^10.7.3 react: ^18.1.0 @@ -280,20 +282,20 @@ importers: examples/minimal: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/non-html-pages: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/portfolio: specifiers: '@astrojs/preact': ^0.1.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 sass: ^1.52.2 dependencies: @@ -307,7 +309,7 @@ importers: specifiers: '@astrojs/node': ^0.1.2 '@astrojs/svelte': ^0.1.4 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 concurrently: ^7.2.1 lightcookie: ^1.0.25 svelte: ^3.48.0 @@ -326,14 +328,14 @@ importers: examples/starter: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: astro: link:../../packages/astro examples/subpath: specifiers: '@astrojs/react': ^0.1.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 react: ^18.1.0 react-dom: ^18.1.0 sass: ^1.52.2 @@ -352,7 +354,7 @@ importers: '@astrojs/react': ^0.1.3 '@astrojs/svelte': ^0.1.4 '@astrojs/vue': ^0.1.5 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 preact: ^10.7.3 react: ^18.1.0 react-dom: ^18.1.0 @@ -375,7 +377,7 @@ importers: examples/with-markdown-plugins: specifiers: '@astrojs/markdown-remark': ^0.11.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 hast-util-select: 5.0.1 rehype-autolink-headings: ^6.1.1 rehype-slug: ^5.0.1 @@ -393,7 +395,7 @@ importers: examples/with-markdown-shiki: specifiers: '@astrojs/markdown-remark': ^0.11.3 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 devDependencies: '@astrojs/markdown-remark': link:../../packages/markdown/remark astro: link:../../packages/astro @@ -408,7 +410,7 @@ importers: '@nanostores/preact': ^0.1.3 '@nanostores/react': ^0.1.5 '@nanostores/vue': ^0.4.1 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 nanostores: ^0.5.12 preact: ^10.7.3 react: ^18.1.0 @@ -436,7 +438,7 @@ importers: examples/with-tailwindcss: specifiers: '@astrojs/tailwind': ^0.2.1 - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 autoprefixer: ^10.4.7 canvas-confetti: ^1.5.1 postcss: ^8.4.14 @@ -451,7 +453,7 @@ importers: examples/with-vite-plugin-pwa: specifiers: - astro: ^1.0.0-beta.51 + astro: ^1.0.0-beta.52 vite-plugin-pwa: 0.11.11 workbox-window: ^6.5.3 devDependencies: @@ -1368,6 +1370,14 @@ importers: dependencies: astro: link:../../.. + packages/astro/test/fixtures/entry-file-names: + specifiers: + '@astrojs/preact': 'workspace:' + astro: workspace:* + dependencies: + '@astrojs/preact': link:../../../../integrations/preact + astro: link:../../.. + packages/astro/test/fixtures/error-react-spectrum: specifiers: '@adobe/react-spectrum': ^3.18.0 @@ -1588,6 +1598,14 @@ importers: dependencies: astro: link:../../.. + packages/astro/test/fixtures/ssr-scripts: + specifiers: + '@astrojs/preact': 'workspace:' + astro: workspace:* + dependencies: + '@astrojs/preact': link:../../../../integrations/preact + astro: link:../../.. + packages/astro/test/fixtures/static-build: specifiers: '@astrojs/preact': workspace:* @@ -8880,6 +8898,11 @@ packages: eslint: 8.17.0 dev: true + /eslint-plugin-no-only-tests/2.6.0: + resolution: {integrity: sha512-T9SmE/g6UV1uZo1oHAqOvL86XWl7Pl2EpRpnLI8g/bkJu+h7XBCB+1LnubRZ2CUQXj805vh4/CYZdnqtVaEo2Q==} + engines: {node: '>=4.0.0'} + dev: true + /eslint-plugin-prettier/4.0.0_ucegkljdju7q4zmvwxzqoprf3y: resolution: {integrity: sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==} engines: {node: '>=6.0.0'}