From 72c2c86e9d7c9b2ce6be13ddb273d4b0b11a5723 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Wed, 9 Mar 2022 15:44:26 -0600 Subject: [PATCH] merge `next` into `main` (#2705) * Unflag the static build (#2652) * Unflag the static build * Only set legacyBuild to false if experimentalSSR is true * Use legacy build when we have to * Put a few more tests into legacy mode * Last two * Make astro-basic use the legacy build * Adds a changeset * Mark the lit test as legacy * Update yarn lock * Update based on feedback * Add --legacy-build flag * Move astro-basic test to use static build (#2682) * Move some tests over to the static build (#2677) * Move some tests over to the static build * Fix assets tests * Fix the assets tests * Fix for the client:only components * Moves asset tests to the static build * Move postcss test over to static build * Bring back legacy build for astro-basic test * Move astro-basic test to use static build * Migrate more tests to the static build (#2693) * fix: disable HMR during build (#2684) * Migrate more tests to the static build * Only prepend links in non-legacy mode * Add the 0-css tests * Convert all CSS tests to the static build * Migrate Astro global tests * Remove .only * Fix static build tests * Migrate a few more * More tests * Move the lit test back to legacy * Increase the test timeout Co-authored-by: Nate Moore * Improve `head` injection behavior (#2436) * feat: add renderHead util to server * feat: remove `layouts` from config, Vite plugin * fix: improve head injection during rendering * chore: update compiler * fix: do not escape links * chore: enter `pre` mode * Replace `send` with `sirv` (#2713) * remove send * Create thick-ravens-chew.md * I feel like I'm going to screw something up * working finally! * rewrite req.url * Add tiny bit of doc * Update .gitignore Co-authored-by: Evan Boehs * Move remaining tests to the static build (#2712) * Move lit test to the static build * Migrate astro-env plugin to work in the static build * Do not remove vite:define * Adds a changeset * Add a warning when passing the --experimental-static-build flag (#2718) * Add a warning when passing the --experimental-static-build flag * Disable the lint warning * [ci] release (next) (#2721) * [ci] release (next) * chore: update changeset Co-authored-by: github-actions[bot] Co-authored-by: Nate Moore * 404 page (#2719) * Fix: build to 404.html in the static build * Adds a changeset * fix pnpm install missing peer deps * fix svelte version in workspace * fix lockfile * fix(webapi): add dev script * improve preview reliability (#2739) * improve preview reliability - fix broken tests * shamefully hoist to unblock * remove lit from test running * chore: update lockfile Co-authored-by: Matthew Phillips Co-authored-by: Evan Boehs Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] Co-authored-by: Fred K. Schott --- .changeset/five-stingrays-collect.md | 5 + .changeset/fresh-ladybugs-think.md | 5 + .changeset/modern-elephants-burn.md | 19 + .changeset/new-pianos-boil.md | 7 + .changeset/pre.json | 57 + .changeset/thick-ravens-chew.md | 5 + .npmrc | 32 +- comp.txt | 0 examples/blog-multiple-authors/package.json | 2 +- examples/blog/package.json | 2 +- examples/component/demo/package.json | 4 +- examples/component/package.json | 2 +- examples/docs/package.json | 8 +- .../docs/src/components/Header/Search.tsx | 1 + examples/docs/src/config.ts | 1 + examples/env-vars/package.json | 2 +- examples/fast-build/package.json | 6 +- examples/framework-alpine/package.json | 2 +- examples/framework-lit/package.json | 2 +- examples/framework-multiple/package.json | 4 +- examples/framework-preact/package.json | 2 +- examples/framework-react/package.json | 2 +- examples/framework-solid/package.json | 2 +- examples/framework-svelte/package.json | 4 +- examples/framework-vue/package.json | 2 +- examples/minimal/package.json | 2 +- examples/non-html-pages/package.json | 2 +- examples/portfolio-svelte/package.json | 4 +- examples/portfolio/package.json | 2 +- examples/ssr/package.json | 7 +- examples/starter/package.json | 2 +- examples/subpath/package.json | 4 +- examples/with-markdown-plugins/package.json | 2 +- examples/with-markdown-shiki/package.json | 2 +- examples/with-markdown/package.json | 4 +- examples/with-nanostores/package.json | 12 +- examples/with-tailwindcss/package.json | 6 +- examples/with-vite-plugin-pwa/package.json | 2 +- package.json | 23 +- packages/astro/CHANGELOG.md | 70 +- packages/astro/package.json | 10 +- packages/astro/src/@types/astro.ts | 24 +- packages/astro/src/core/app/index.ts | 2 +- packages/astro/src/core/build/index.ts | 2 +- packages/astro/src/core/build/static-build.ts | 38 +- packages/astro/src/core/config.ts | 21 +- packages/astro/src/core/preview/index.ts | 91 +- packages/astro/src/core/render/core.ts | 19 +- packages/astro/src/core/render/dev/index.ts | 80 +- packages/astro/src/core/render/result.ts | 8 +- packages/astro/src/core/render/sitemap.ts | 1 - .../astro/src/core/routing/manifest/create.ts | 2 +- packages/astro/src/runtime/server/index.ts | 70 +- packages/astro/src/runtime/server/metadata.ts | 16 + .../astro/src/vite-plugin-astro/compile.ts | 10 +- packages/astro/src/vite-plugin-env/index.ts | 56 +- packages/astro/test/0-css.test.js | 26 +- packages/astro/test/astro-assets.test.js | 19 +- packages/astro/test/astro-basic.test.js | 4 +- packages/astro/test/astro-client-only.test.js | 19 +- packages/astro/test/astro-components.test.js | 56 - .../test/astro-css-bundling-import.test.js | 7 +- .../astro-css-bundling-nested-layouts.test.js | 38 - .../astro/test/astro-css-bundling.test.js | 28 +- packages/astro/test/astro-dynamic.test.js | 12 +- packages/astro/test/astro-envs.test.js | 12 +- packages/astro/test/astro-global.test.js | 9 +- .../astro/test/astro-partial-html.test.js | 11 +- packages/astro/test/astro-scripts.test.js | 15 +- packages/astro/test/builtins.test.js | 27 - packages/astro/test/cli.test.js | 51 - packages/astro/test/custom-elements.test.js | 4 +- .../test/fixtures/0-css/src/pages/index.astro | 15 +- .../astro-assets/src/pages/index.astro | 2 +- .../src/components/Component.astro | 11 - .../src/components/Component.jsx | 5 - .../src/components/Component.svelte | 3 - .../src/components/Component.vue | 9 - .../src/components/Props-Component.astro | 6 - .../astro-components/src/pages/client.astro | 9 - .../src/pages/frontmatter-component.astro | 6 - .../astro-components/src/pages/index.astro | 9 - .../src/pages/props-shadowing.astro | 4 - .../src/pages/undefined-component.astro | 11 - .../src/layouts/BaseLayout.astro | 27 - .../src/layouts/PageLayout.astro | 12 - .../src/pages/page-1.astro | 15 - .../src/pages/page-2.astro | 9 - .../src/styles/page-one.css | 3 - .../src/styles/page-two.css | 3 - .../src/styles/site.css | 7 - .../astro-css-bundling/src/pages/index.astro | 8 +- .../astro-css-bundling/src/pages/one.astro | 6 +- .../src/pages/preload-merge.astro | 17 - .../src/pages/preload.astro | 14 - .../astro-css-bundling/src/pages/two.astro | 8 +- .../src/components/ChildResolve.astro | 5 - .../src/components/nested/InnerChild.astro | 6 - .../src/components/nested/images/penguin.png | Bin 77977 -> 0 bytes .../astro-global/src/pages/resolve.astro | 14 - .../src/components/NoHoistClassic.astro | 5 +- .../src/components/NoHoistModule.astro | 5 +- .../astro-scripts/src/components/Widget.astro | 2 +- .../src/components/Widget2.astro | 2 +- .../astro/test/fixtures/builtins/package.json | 9 - .../builtins/packages/dep/CHANGELOG.md | 8 - .../fixtures/builtins/packages/dep/main.js | 10 - .../builtins/packages/dep/package.json | 7 - .../builtins/src/components/Version.astro | 9 - .../fixtures/builtins/src/pages/bare.astro | 12 - .../fixtures/builtins/src/pages/index.astro | 16 - .../astro/test/fixtures/postcss/package.json | 3 +- .../fixtures/postcss/src/pages/index.astro | 7 +- .../static-build-frameworks/package.json | 3 +- .../src/components/LCounter.js | 34 - .../src/pages/lit.astro | 12 - .../fixtures/status-code/src/pages/404.astro | 8 + .../status-code/src/pages/index.astro | 8 + packages/astro/test/postcss.test.js | 6 +- packages/astro/test/preview-routing.test.js | 3 + packages/astro/test/remote-css.test.js | 2 +- .../test/static-build-frameworks.test.js | 6 +- .../test/static-build-page-url-format.test.js | 4 +- packages/astro/test/static-build.test.js | 32 +- packages/astro/test/status-page.test.js | 19 + .../renderers/renderer-svelte/package.json | 1 + packages/renderers/renderer-vue/package.json | 1 + packages/webapi/package.json | 2 + pnpm-lock.yaml | 3302 +++++++++-------- scripts/memory/index.js | 2 +- 130 files changed, 2439 insertions(+), 2455 deletions(-) create mode 100644 .changeset/five-stingrays-collect.md create mode 100644 .changeset/fresh-ladybugs-think.md create mode 100644 .changeset/modern-elephants-burn.md create mode 100644 .changeset/new-pianos-boil.md create mode 100644 .changeset/pre.json create mode 100644 .changeset/thick-ravens-chew.md delete mode 100644 comp.txt delete mode 100644 packages/astro/test/astro-components.test.js delete mode 100644 packages/astro/test/astro-css-bundling-nested-layouts.test.js delete mode 100644 packages/astro/test/builtins.test.js delete mode 100644 packages/astro/test/cli.test.js delete mode 100644 packages/astro/test/fixtures/astro-components/src/components/Component.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/components/Component.jsx delete mode 100644 packages/astro/test/fixtures/astro-components/src/components/Component.svelte delete mode 100644 packages/astro/test/fixtures/astro-components/src/components/Component.vue delete mode 100644 packages/astro/test/fixtures/astro-components/src/components/Props-Component.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/pages/client.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/pages/frontmatter-component.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/pages/index.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/pages/props-shadowing.astro delete mode 100644 packages/astro/test/fixtures/astro-components/src/pages/undefined-component.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/layouts/BaseLayout.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/layouts/PageLayout.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-1.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-2.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-one.css delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-two.css delete mode 100644 packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/site.css delete mode 100644 packages/astro/test/fixtures/astro-css-bundling/src/pages/preload-merge.astro delete mode 100644 packages/astro/test/fixtures/astro-css-bundling/src/pages/preload.astro delete mode 100644 packages/astro/test/fixtures/astro-global/src/components/ChildResolve.astro delete mode 100644 packages/astro/test/fixtures/astro-global/src/components/nested/InnerChild.astro delete mode 100644 packages/astro/test/fixtures/astro-global/src/components/nested/images/penguin.png delete mode 100644 packages/astro/test/fixtures/astro-global/src/pages/resolve.astro delete mode 100644 packages/astro/test/fixtures/builtins/package.json delete mode 100644 packages/astro/test/fixtures/builtins/packages/dep/CHANGELOG.md delete mode 100644 packages/astro/test/fixtures/builtins/packages/dep/main.js delete mode 100644 packages/astro/test/fixtures/builtins/packages/dep/package.json delete mode 100644 packages/astro/test/fixtures/builtins/src/components/Version.astro delete mode 100644 packages/astro/test/fixtures/builtins/src/pages/bare.astro delete mode 100644 packages/astro/test/fixtures/builtins/src/pages/index.astro delete mode 100644 packages/astro/test/fixtures/static-build-frameworks/src/components/LCounter.js delete mode 100644 packages/astro/test/fixtures/static-build-frameworks/src/pages/lit.astro create mode 100644 packages/astro/test/fixtures/status-code/src/pages/404.astro create mode 100644 packages/astro/test/fixtures/status-code/src/pages/index.astro create mode 100644 packages/astro/test/status-page.test.js diff --git a/.changeset/five-stingrays-collect.md b/.changeset/five-stingrays-collect.md new file mode 100644 index 0000000000..b4d51aa5b0 --- /dev/null +++ b/.changeset/five-stingrays-collect.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes the static build to write to 404.html diff --git a/.changeset/fresh-ladybugs-think.md b/.changeset/fresh-ladybugs-think.md new file mode 100644 index 0000000000..bdf29ac191 --- /dev/null +++ b/.changeset/fresh-ladybugs-think.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes use of private .env variables with the static build diff --git a/.changeset/modern-elephants-burn.md b/.changeset/modern-elephants-burn.md new file mode 100644 index 0000000000..b868ecfb68 --- /dev/null +++ b/.changeset/modern-elephants-burn.md @@ -0,0 +1,19 @@ +--- +'astro': minor +--- + +New default build strategy + +This change marks the "static build" as the new default build strategy. If you are unfamiliar with this build strategy check out the [migration guide](https://docs.astro.build/en/migrate/#planned-deprecations) on how to change your code to be compatible with this new bulid strategy. + +If you'd like to keep using the old build strategy, use the flag `--legacy-build` both in your `astro dev` and `astro build` scripts, for ex: + +```json +{ + "scripts": { + "build": "astro build --legacy-build" + } +} +``` + +Note that the legacy build *is* deprecated and will be removed in a future version. You should only use this flag until you have the time to migration your code. diff --git a/.changeset/new-pianos-boil.md b/.changeset/new-pianos-boil.md new file mode 100644 index 0000000000..bb3c1a728b --- /dev/null +++ b/.changeset/new-pianos-boil.md @@ -0,0 +1,7 @@ +--- +'astro': minor +--- + +## Updated `` and `` behavior + +Since `astro@0.21`, Astro placed certain restrictions on what files could use `` or `` tags. In `astro@0.24`, the restrictions have been lifted. Astro will be able to correctly handle `` and `` tags in _any_ component, not just those in `src/pages/` or `src/layouts/`. diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 0000000000..9532184e9a --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,57 @@ +{ + "mode": "pre", + "tag": "next", + "initialVersions": { + "@example/blog": "0.0.1", + "@example/blog-multiple-authors": "0.0.1", + "@example/component": "0.0.1", + "@example/my-component-demo": "0.0.1", + "@example/my-component": "0.0.1", + "@example/docs": "0.0.1", + "@example/env-vars": "0.0.1", + "@example/fast-build": "0.0.1", + "@example/framework-alpine": "0.0.1", + "@example/framework-lit": "0.0.1", + "@example/framework-multiple": "0.0.1", + "@example/framework-preact": "0.0.1", + "@example/framework-react": "0.0.1", + "@example/framework-solid": "0.0.1", + "@example/framework-svelte": "0.0.1", + "@example/framework-vue": "0.0.1", + "@example/minimal": "0.0.1", + "@example/non-html-pages": "0.0.1", + "@example/portfolio": "0.0.1", + "@example/portfolio-svelte": "0.0.1", + "@example/ssr": "0.0.1", + "@example/starter": "0.0.1", + "@example/subpath": "0.0.1", + "@example/with-markdown": "0.0.1", + "@example/with-markdown-plugins": "0.0.2", + "@example/with-markdown-shiki": "0.0.1", + "@example/with-nanostores": "0.0.1", + "@example/with-tailwindcss": "0.0.1", + "@example/with-vite-plugin-pwa": "0.0.1", + "astro": "0.23.3", + "@astrojs/parser": "0.22.1", + "@astrojs/prism": "0.4.0", + "@astrojs/test-custom-element-renderer": "0.1.0", + "@astrojs/test-static-build-pkg": "0.0.3", + "create-astro": "0.7.1", + "@astrojs/markdown-remark": "0.6.2", + "@astrojs/renderer-lit": "0.4.0", + "@astrojs/renderer-preact": "0.5.0", + "@astrojs/renderer-react": "0.5.0", + "@astrojs/renderer-solid": "0.4.0", + "@astrojs/renderer-svelte": "0.4.0", + "@astrojs/renderer-vue": "0.4.0", + "astro-scripts": "0.0.1", + "astro.build": "0.0.1", + "docs": "0.0.7" + }, + "changesets": [ + "fresh-ladybugs-think", + "modern-elephants-burn", + "new-pianos-boil", + "thick-ravens-chew" + ] +} diff --git a/.changeset/thick-ravens-chew.md b/.changeset/thick-ravens-chew.md new file mode 100644 index 0000000000..3e7710d428 --- /dev/null +++ b/.changeset/thick-ravens-chew.md @@ -0,0 +1,5 @@ +--- +"astro": patch +--- + +Replace `send` dependency with `sirv` diff --git a/.npmrc b/.npmrc index 6e736d1958..492d203578 100644 --- a/.npmrc +++ b/.npmrc @@ -3,19 +3,19 @@ prefer-workspace-packages=true link-workspace-packages=true save-workspace-protocol=false # This prevents the examples to have the `workspace:` prefix -use-node-version=14.19.0 - -# Rather than shamefully hoisting everything, just make problematic packages public -public-hoist-pattern[]=autoprefixer -public-hoist-pattern[]=astro -public-hoist-pattern[]=remark-* -public-hoist-pattern[]=rehype-* -public-hoist-pattern[]=react -public-hoist-pattern[]=react-dom -public-hoist-pattern[]=preact -public-hoist-pattern[]=preact-render-to-string -public-hoist-pattern[]=vue -public-hoist-pattern[]=svelte -public-hoist-pattern[]=solid-js -public-hoist-pattern[]=lit -public-hoist-pattern[]=@webcomponents/template-shadowroot +shamefully-hoist=true +# TODO: We would like to move to individual opt-in hoisting, but Astro was not originally +# written with this in mind. In the future, it would be good to hoist individual packages only. +# public-hoist-pattern[]=autoprefixer +# public-hoist-pattern[]=astro +# public-hoist-pattern[]=remark-* +# public-hoist-pattern[]=rehype-* +# public-hoist-pattern[]=react +# public-hoist-pattern[]=react-dom +# public-hoist-pattern[]=preact +# public-hoist-pattern[]=preact-render-to-string +# public-hoist-pattern[]=vue +# public-hoist-pattern[]=svelte +# public-hoist-pattern[]=solid-js +# public-hoist-pattern[]=lit +# public-hoist-pattern[]=@webcomponents/template-shadowroot diff --git a/comp.txt b/comp.txt deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/examples/blog-multiple-authors/package.json b/examples/blog-multiple-authors/package.json index 1246009539..2d8b33dc27 100644 --- a/examples/blog-multiple-authors/package.json +++ b/examples/blog-multiple-authors/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7", + "astro": "^0.24.0-next.0", "sass": "^1.49.8" } } diff --git a/examples/blog/package.json b/examples/blog/package.json index 68c0ca62c0..737c86a511 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7", + "astro": "^0.24.0-next.0", "@astrojs/renderer-preact": "^0.5.0" } } diff --git a/examples/component/demo/package.json b/examples/component/demo/package.json index 6fb878f6e3..438e6485e4 100644 --- a/examples/component/demo/package.json +++ b/examples/component/demo/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7", - "@example/my-component": "workspace:*" + "@example/my-component": "workspace:*", + "astro": "^0.24.0-next.0" } } diff --git a/examples/component/package.json b/examples/component/package.json index dc1c119cfd..613eac1a91 100644 --- a/examples/component/package.json +++ b/examples/component/package.json @@ -8,6 +8,6 @@ "serve": "astro --project-root demo preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/docs/package.json b/examples/docs/package.json index 620bf726f9..406c1f51fe 100644 --- a/examples/docs/package.json +++ b/examples/docs/package.json @@ -9,12 +9,16 @@ "preview": "astro preview" }, "dependencies": { + "@algolia/client-search": "^4.12.0", "@docsearch/css": "^3.0.0", - "@docsearch/react": "^1.0.0-alpha.28" + "@docsearch/react": "^3.0.0", + "@types/react": "^17.0.39", + "react": "^17.0.2", + "react-dom": "^17.0.2" }, "devDependencies": { "@astrojs/renderer-react": "^0.5.0", "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/docs/src/components/Header/Search.tsx b/examples/docs/src/components/Header/Search.tsx index bbe02073dd..ebc563c617 100644 --- a/examples/docs/src/components/Header/Search.tsx +++ b/examples/docs/src/components/Header/Search.tsx @@ -57,6 +57,7 @@ export default function Search() { initialScrollY={window.scrollY} onClose={onClose} indexName={(CONFIG as any).ALGOLIA.indexName} + appId={(CONFIG as any).ALGOLIA.appId} apiKey={(CONFIG as any).ALGOLIA.apiKey} transformItems={(items) => { return items.map((item) => { diff --git a/examples/docs/src/config.ts b/examples/docs/src/config.ts index 5953dd97a5..174765d272 100644 --- a/examples/docs/src/config.ts +++ b/examples/docs/src/config.ts @@ -26,6 +26,7 @@ export const KNOWN_LANGUAGES = { // See "Algolia" section of the README for more information. // export const ALGOLIA = { // indexName: 'XXXXXXXXXX', +// appId: 'XXXXXXXXXX', // apiKey: 'XXXXXXXXXX', // } diff --git a/examples/env-vars/package.json b/examples/env-vars/package.json index 5b1dc86234..1751b14a7e 100644 --- a/examples/env-vars/package.json +++ b/examples/env-vars/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/fast-build/package.json b/examples/fast-build/package.json index 1259721d0e..0a7bd74ff3 100644 --- a/examples/fast-build/package.json +++ b/examples/fast-build/package.json @@ -12,10 +12,10 @@ "devDependencies": { "@astrojs/renderer-vue": "^0.4.0", "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7", "sass": "^1.49.8", + "astro": "^0.24.0-next.0", + "preact": "~10.6.5", "unocss": "^0.15.5", - "vite-imagetools": "^4.0.1", - "@astrojs/renderer-vue": "^0.4.0" + "vite-imagetools": "^4.0.1" } } diff --git a/examples/framework-alpine/package.json b/examples/framework-alpine/package.json index 49384258ae..87154d440a 100644 --- a/examples/framework-alpine/package.json +++ b/examples/framework-alpine/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-lit/package.json b/examples/framework-lit/package.json index e15c32b8e6..61d97814e7 100644 --- a/examples/framework-lit/package.json +++ b/examples/framework-lit/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-lit": "^0.4.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-multiple/package.json b/examples/framework-multiple/package.json index 5b3c53da50..aef07762e9 100644 --- a/examples/framework-multiple/package.json +++ b/examples/framework-multiple/package.json @@ -13,8 +13,8 @@ "@astrojs/renderer-preact": "^0.5.0", "@astrojs/renderer-react": "^0.5.0", "@astrojs/renderer-solid": "^0.4.0", - "@astrojs/renderer-svelte": "^0.4.0", + "@astrojs/renderer-svelte": "^0.5.1", "@astrojs/renderer-vue": "^0.4.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-preact/package.json b/examples/framework-preact/package.json index 1fa0b2a645..7c946770e1 100644 --- a/examples/framework-preact/package.json +++ b/examples/framework-preact/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-react/package.json b/examples/framework-react/package.json index 4d1762a87c..7b0d66d1aa 100644 --- a/examples/framework-react/package.json +++ b/examples/framework-react/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-react": "^0.5.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-solid/package.json b/examples/framework-solid/package.json index 5bb22ea553..c782f35332 100644 --- a/examples/framework-solid/package.json +++ b/examples/framework-solid/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-solid": "^0.4.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-svelte/package.json b/examples/framework-svelte/package.json index 7dd4d12e20..83fecfe4fc 100644 --- a/examples/framework-svelte/package.json +++ b/examples/framework-svelte/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "@astrojs/renderer-svelte": "^0.4.0", - "astro": "^0.23.7" + "@astrojs/renderer-svelte": "^0.5.1", + "astro": "^0.24.0-next.0" } } diff --git a/examples/framework-vue/package.json b/examples/framework-vue/package.json index 8662c303fe..fdce32fc4d 100644 --- a/examples/framework-vue/package.json +++ b/examples/framework-vue/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-vue": "^0.4.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/minimal/package.json b/examples/minimal/package.json index aa4ce339ec..16bea438c5 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/non-html-pages/package.json b/examples/non-html-pages/package.json index 665ca4a452..837ead14b7 100644 --- a/examples/non-html-pages/package.json +++ b/examples/non-html-pages/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/portfolio-svelte/package.json b/examples/portfolio-svelte/package.json index b9c83a2e8d..73ade49a07 100644 --- a/examples/portfolio-svelte/package.json +++ b/examples/portfolio-svelte/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "@astrojs/renderer-svelte": "^0.4.0", - "astro": "^0.23.7" + "@astrojs/renderer-svelte": "^0.5.1", + "astro": "^0.24.0-next.0" } } diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index 744cfaddd5..5629af7d40 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/ssr/package.json b/examples/ssr/package.json index 9da47f6a35..0075e0f30f 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -11,10 +11,9 @@ "server": "node server/server.mjs" }, "devDependencies": { - "@astrojs/renderer-svelte": "^0.4.0", - "astro": "^0.23.7", + "@astrojs/renderer-svelte": "^0.5.1", + "astro": "^0.24.0-next.0", "unocss": "^0.15.5", - "vite-imagetools": "^4.0.1", - "@astrojs/renderer-svelte": "^0.5.1" + "vite-imagetools": "^4.0.1" } } diff --git a/examples/starter/package.json b/examples/starter/package.json index 80bdb70f47..963e78d530 100644 --- a/examples/starter/package.json +++ b/examples/starter/package.json @@ -9,6 +9,6 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/subpath/package.json b/examples/subpath/package.json index 43b01d9f7b..55001eee2f 100644 --- a/examples/subpath/package.json +++ b/examples/subpath/package.json @@ -9,7 +9,7 @@ "preview": "astro preview" }, "devDependencies": { - "astro": "^0.23.7", - "@astrojs/renderer-react": "^0.5.0" + "@astrojs/renderer-react": "^0.5.0", + "astro": "^0.24.0-next.0" } } diff --git a/examples/with-markdown-plugins/package.json b/examples/with-markdown-plugins/package.json index a275c36120..6092c7ec39 100644 --- a/examples/with-markdown-plugins/package.json +++ b/examples/with-markdown-plugins/package.json @@ -10,7 +10,7 @@ }, "devDependencies": { "@astrojs/markdown-remark": "^0.6.1", - "astro": "^0.23.7", + "astro": "^0.24.0-next.0", "hast-util-select": "5.0.1", "rehype-autolink-headings": "^6.1.0", "rehype-slug": "^5.0.0", diff --git a/examples/with-markdown-shiki/package.json b/examples/with-markdown-shiki/package.json index 9ec9319503..83b6a66a90 100644 --- a/examples/with-markdown-shiki/package.json +++ b/examples/with-markdown-shiki/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@astrojs/markdown-remark": "^0.6.1", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/with-markdown/package.json b/examples/with-markdown/package.json index 144e8d6de1..d5374964c3 100644 --- a/examples/with-markdown/package.json +++ b/examples/with-markdown/package.json @@ -11,9 +11,9 @@ "devDependencies": { "@astrojs/renderer-preact": "^0.5.0", "@astrojs/renderer-react": "^0.5.0", - "@astrojs/renderer-svelte": "^0.4.0", + "@astrojs/renderer-svelte": "^0.5.1", "@astrojs/renderer-vue": "^0.4.0", "@astrojs/markdown-remark": "^0.6.1", - "astro": "^0.23.7" + "astro": "^0.24.0-next.0" } } diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json index 6777c58d13..405842aec5 100644 --- a/examples/with-nanostores/package.json +++ b/examples/with-nanostores/package.json @@ -13,18 +13,18 @@ "@nanostores/react": "^0.1.5", "@nanostores/vue": "^0.4.1", "nanostores": "^0.5.7", - "solid-nanostores": "0.0.6" + "solid-nanostores": "0.0.6", + "preact": "^10.6.5", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "vue": "^3.2.0" }, "devDependencies": { "@astrojs/renderer-react": "^0.5.0", - "@astrojs/renderer-svelte": "^0.4.0", "@astrojs/renderer-vue": "^0.4.0", "@astrojs/renderer-preact": "^0.5.0", "@astrojs/renderer-solid": "^0.4.0", - "astro": "^0.23.7", - "@astrojs/renderer-preact": "^0.5.0", - "@astrojs/renderer-react": "^0.5.0", "@astrojs/renderer-svelte": "^0.5.1", - "@astrojs/renderer-vue": "^0.4.0" + "astro": "^0.24.0-next.0" } } diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index a34e085f39..4e99fdef63 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -10,9 +10,9 @@ }, "devDependencies": { "@astrojs/renderer-preact": "^0.5.0", - "astro": "^0.23.7", + "postcss": "^8.3.8", + "astro": "^0.24.0-next.0", "autoprefixer": "^10.4.0", - "tailwindcss": "^3.0.5", - "@astrojs/renderer-preact": "^0.5.0" + "tailwindcss": "^3.0.5" } } diff --git a/examples/with-vite-plugin-pwa/package.json b/examples/with-vite-plugin-pwa/package.json index 9324eef671..2c7c5d408f 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": "^0.23.7", + "astro": "^0.24.0-next.0", "vite-plugin-pwa": "0.11.11", "workbox-window": "^6.5.0" } diff --git a/package.json b/package.json index b4c1e386df..13f6e04826 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,8 @@ "peerDependencyRules": { "ignoreMissing": [ "@babel/core", - "@babel/plugin-transform-react-jsx" + "@babel/plugin-transform-react-jsx", + "vite" ] } }, @@ -51,20 +52,20 @@ "@astrojs/webapi": "workspace:*" }, "devDependencies": { - "@changesets/changelog-github": "^0.4.2", - "@changesets/cli": "^2.16.0", - "@octokit/action": "^3.15.4", - "@typescript-eslint/eslint-plugin": "^5.0.0", - "@typescript-eslint/parser": "^5.0.0", + "@changesets/changelog-github": "^0.4.3", + "@changesets/cli": "^2.21.1", + "@octokit/action": "^3.18.0", + "@typescript-eslint/eslint-plugin": "^5.14.0", + "@typescript-eslint/parser": "^5.14.0", "del": "^6.0.0", "esbuild": "0.13.7", - "eslint": "^8.0.1", - "eslint-config-prettier": "^8.3.0", + "eslint": "^8.10.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-prettier": "^4.0.0", - "execa": "^6.0.0", - "prettier": "^2.4.1", + "execa": "^6.1.0", + "prettier": "^2.5.1", "pretty-bytes": "^6.0.0", - "tiny-glob": "^0.2.8", + "tiny-glob": "^0.2.9", "turbo": "^1.1.5", "typescript": "4.5.2" } diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md index fa4f3a6bca..142756d04b 100644 --- a/packages/astro/CHANGELOG.md +++ b/packages/astro/CHANGELOG.md @@ -1,5 +1,35 @@ # astro +## 0.24.0-next.0 + +### Minor Changes + +- [#2705](https://github.com/withastro/astro/pull/2705) [`8ce63ee6`](https://github.com/withastro/astro/commit/8ce63ee658677ecabcb3068f00413b51e7db30ef) Thanks [@natemoo-re](https://github.com/natemoo-re)! - New default build strategy + + This change marks the "static build" as the new default build strategy. If you are unfamiliar with this build strategy check out the [migration guide](https://docs.astro.build/en/migrate/#planned-deprecations) on how to change your code to be compatible with this new bulid strategy. + + If you'd like to keep using the old build strategy, use the flag `--legacy-build` both in your `astro dev` and `astro build` scripts, for ex: + + ```json + { + "scripts": { + "build": "astro build --legacy-build" + } + } + ``` + + Note that the legacy build _is_ deprecated and will be removed in a future version. You should only use this flag until you have the time to migration your code. + + - **Updated `` and `` behavior** + + Since `astro@0.21`, Astro placed certain restrictions on what files could use `` or `` tags. In `astro@0.24`, the restrictions have been lifted. Astro will be able to correctly handle `` and `` tags in _any_ component, not just those in `src/pages/` or `src/layouts/`. + +### Patch Changes + +- [#2705](https://github.com/withastro/astro/pull/2705) [`176d4082`](https://github.com/withastro/astro/commit/176d4082ca642e3d7b996529f1efed7048b4d04f) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Fixes use of private .env variables with the static build + +* [#2705](https://github.com/withastro/astro/pull/2705) [`a483c044`](https://github.com/withastro/astro/commit/a483c0446ba222edf4258f4683cd918ea209b8f4) Thanks [@natemoo-re](https://github.com/natemoo-re)! - Replace `send` dependency with `sirv` + ## 0.23.7 ### Patch Changes @@ -96,12 +126,12 @@ ```typescript // src/pages/company.json.ts export async function get() { - return { - body: JSON.stringify({ - name: 'Astro Technology Company', - url: 'https://astro.build/', - }), - }; + return { + body: JSON.stringify({ + name: 'Astro Technology Company', + url: 'https://astro.build/', + }), + }; } ``` @@ -263,12 +293,12 @@ ```typescript // src/pages/company.json.ts export async function get() { - return { - body: JSON.stringify({ - name: 'Astro Technology Company', - url: 'https://astro.build/', - }), - }; + return { + body: JSON.stringify({ + name: 'Astro Technology Company', + url: 'https://astro.build/', + }), + }; } ``` @@ -1623,10 +1653,10 @@ For convenience, you may now also move your `astro.config.js` file to a top-leve ```js export default { - markdownOptions: { - remarkPlugins: ['remark-slug', ['remark-autolink-headings', { behavior: 'prepend' }]], - rehypePlugins: ['rehype-slug', ['rehype-autolink-headings', { behavior: 'prepend' }]], - }, + markdownOptions: { + remarkPlugins: ['remark-slug', ['remark-autolink-headings', { behavior: 'prepend' }]], + rehypePlugins: ['rehype-slug', ['rehype-autolink-headings', { behavior: 'prepend' }]], + }, }; ``` @@ -1646,10 +1676,10 @@ For convenience, you may now also move your `astro.config.js` file to a top-leve ```js export default { - name: '@matthewp/my-renderer', - server: './server.js', - client: './client.js', - hydrationPolyfills: ['./my-polyfill.js'], + name: '@matthewp/my-renderer', + server: './server.js', + client: './client.js', + hydrationPolyfills: ['./my-polyfill.js'], }; ``` diff --git a/packages/astro/package.json b/packages/astro/package.json index 508ddfb844..69818591e8 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "astro", - "version": "0.23.7", + "version": "0.24.0-next.0", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "type": "module", "author": "withastro", @@ -54,11 +54,11 @@ "dev": "astro-scripts dev \"src/**/*.ts\"", "postbuild": "astro-scripts copy \"src/**/*.astro\"", "benchmark": "node test/benchmark/dev.bench.js && node test/benchmark/build.bench.js", - "test": "mocha --parallel --timeout 15000 --ignore **/lit-element.test.js && mocha **/lit-element.test.js", - "test:match": "mocha --timeout 15000 -g" + "test": "mocha --parallel --timeout 20000 --ignore **/lit-element.test.js && mocha --timeout 20000 **/lit-element.test.js", + "test:match": "mocha --timeout 20000 -g" }, "dependencies": { - "@astrojs/compiler": "^0.11.4", + "@astrojs/compiler": "^0.12.0-next.8", "@astrojs/language-server": "^0.8.6", "@astrojs/markdown-remark": "^0.6.4", "@astrojs/prism": "0.4.0", @@ -95,7 +95,7 @@ "resolve": "^1.20.0", "rollup": "^2.64.0", "semver": "^7.3.5", - "send": "^0.17.1", + "sirv": "^2.0.2", "serialize-javascript": "^6.0.0", "shiki": "^0.10.0", "shorthash": "^0.0.2", diff --git a/packages/astro/src/@types/astro.ts b/packages/astro/src/@types/astro.ts index dab4b9a658..e945b8dd62 100644 --- a/packages/astro/src/@types/astro.ts +++ b/packages/astro/src/@types/astro.ts @@ -27,8 +27,10 @@ export interface CLIFlags { hostname?: string; port?: number; config?: string; + /** @deprecated */ experimentalStaticBuild?: boolean; experimentalSsr?: boolean; + legacyBuild?: boolean; drafts?: boolean; } @@ -266,12 +268,19 @@ export interface AstroUserConfig { */ drafts?: boolean; /** - * Experimental: Enables "static build mode" for faster builds. + * Enables "legacy build mode" for compatibility with older Astro versions. * Default: false */ + legacyBuild?: boolean; + /** + * @deprecated + * Experimental: Enables "static build mode" for faster builds. + * Default: true + */ experimentalStaticBuild?: boolean; /** * Enable a build for SSR support. + * Default: false */ experimentalSsr?: boolean; }; @@ -506,17 +515,6 @@ export type Params = Record; export type Props = Record; -export interface RenderPageOptions { - request: { - params?: Params; - url: URL; - canonicalURL: URL; - }; - children: any[]; - props: Props; - css?: string[]; -} - type Body = string; export interface EndpointOutput { @@ -634,7 +632,7 @@ export interface SSRElement { export interface SSRMetadata { renderers: Renderer[]; pathname: string; - experimentalStaticBuild: boolean; + legacyBuild: boolean; } export interface SSRResult { diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index aba580f5d0..c31c37f31d 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -46,7 +46,7 @@ export class App { const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site); return render({ - experimentalStaticBuild: true, + legacyBuild: false, links, logging: defaultLogOptions, markdownRender: manifest.markdown.render, diff --git a/packages/astro/src/core/build/index.ts b/packages/astro/src/core/build/index.ts index fba2b58f2e..0e5a50f223 100644 --- a/packages/astro/src/core/build/index.ts +++ b/packages/astro/src/core/build/index.ts @@ -110,7 +110,7 @@ class AstroBuilder { timer.buildStart = performance.now(); // Use the new faster static based build. - if (this.config.buildOptions.experimentalStaticBuild) { + if (!this.config.buildOptions.legacyBuild) { await staticBuild({ allPages, astroConfig: this.config, diff --git a/packages/astro/src/core/build/static-build.ts b/packages/astro/src/core/build/static-build.ts index 9224a03cec..a54236dd66 100644 --- a/packages/astro/src/core/build/static-build.ts +++ b/packages/astro/src/core/build/static-build.ts @@ -38,9 +38,10 @@ export interface StaticBuildOptions { const MAX_CONCURRENT_RENDERS = 10; +const STATUS_CODE_PAGES = new Set(['/404', '/500']); + function addPageName(pathname: string, opts: StaticBuildOptions): void { - const pathrepl = opts.astroConfig.buildOptions.pageUrlFormat === 'directory' ? '/index.html' : pathname === '/' ? 'index.html' : '.html'; - opts.pageNames.push(pathname.replace(/\/?$/, pathrepl).replace(/^\//, '')); + opts.pageNames.push(pathname.replace(/\/?$/, '/').replace(/^\//, '')); } // Gives back a facadeId that is relative to the root. @@ -131,6 +132,8 @@ export async function staticBuild(opts: StaticBuildOptions) { const topLevelImports = new Set([ // Any component that gets hydrated ...metadata.hydratedComponentPaths(), + // Client-only components + ...metadata.clientOnlyComponentPaths(), // Any hydration directive like astro/client/idle.js ...metadata.hydrationDirectiveSpecifiers(), // The client path for each renderer @@ -182,6 +185,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp logLevel: 'error', mode: 'production', build: { + ...viteConfig.build, emptyOutDir: false, manifest: ssr, minify: false, @@ -360,12 +364,12 @@ async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: G debug('build', `Generating: ${pathname}`); const site = astroConfig.buildOptions.site; - const links = createLinkStylesheetElementSet(linkIds, site); + const links = createLinkStylesheetElementSet(linkIds.reverse(), site); const scripts = createModuleScriptElementWithSrcSet(hoistedId ? [hoistedId] : [], site); try { const html = await render({ - experimentalStaticBuild: true, + legacyBuild: false, links, logging, markdownRender: astroConfig.markdownOptions.render, @@ -454,8 +458,7 @@ async function generateManifest(result: RollupOutput, opts: StaticBuildOptions, } function getOutRoot(astroConfig: AstroConfig): URL { - const rootPathname = appendForwardSlash(astroConfig.buildOptions.site ? new URL(astroConfig.buildOptions.site).pathname : '/'); - return new URL('.' + rootPathname, astroConfig.dist); + return new URL('./', astroConfig.dist); } function getServerRoot(astroConfig: AstroConfig): URL { @@ -479,10 +482,16 @@ function getOutFolder(astroConfig: AstroConfig, pathname: string, routeType: Rou return new URL('.' + appendForwardSlash(npath.dirname(pathname)), outRoot); case 'page': switch (astroConfig.buildOptions.pageUrlFormat) { - case 'directory': + case 'directory': { + if(STATUS_CODE_PAGES.has(pathname)) { + return new URL('.' + appendForwardSlash(npath.dirname(pathname)), outRoot); + } return new URL('.' + appendForwardSlash(pathname), outRoot); - case 'file': + } + case 'file': { return new URL('.' + appendForwardSlash(npath.dirname(pathname)), outRoot); + } + } } } @@ -493,10 +502,17 @@ function getOutFile(astroConfig: AstroConfig, outFolder: URL, pathname: string, return new URL(npath.basename(pathname), outFolder); case 'page': switch (astroConfig.buildOptions.pageUrlFormat) { - case 'directory': + case 'directory': { + if(STATUS_CODE_PAGES.has(pathname)) { + const baseName = npath.basename(pathname); + return new URL('./' + (baseName || 'index') + '.html', outFolder); + } return new URL('./index.html', outFolder); - case 'file': - return new URL('./' + npath.basename(pathname) + '.html', outFolder); + } + case 'file': { + const baseName = npath.basename(pathname); + return new URL('./' + (baseName || 'index') + '.html', outFolder); + } } } } diff --git a/packages/astro/src/core/config.ts b/packages/astro/src/core/config.ts index 296800388a..4efbb4c7b3 100644 --- a/packages/astro/src/core/config.ts +++ b/packages/astro/src/core/config.ts @@ -26,11 +26,6 @@ export const AstroConfigSchema = z.object({ .optional() .default('./src/pages') .transform((val) => new URL(val)), - layouts: z - .string() - .optional() - .default('./src/layouts') - .transform((val) => new URL(val)), public: z .string() .optional() @@ -60,7 +55,8 @@ export const AstroConfigSchema = z.object({ .union([z.literal('file'), z.literal('directory')]) .optional() .default('directory'), - experimentalStaticBuild: z.boolean().optional().default(false), + legacyBuild: z.boolean().optional().default(false), + experimentalStaticBuild: z.boolean().optional().default(true), experimentalSsr: z.boolean().optional().default(false), drafts: z.boolean().optional().default(false), }) @@ -98,10 +94,6 @@ export async function validateConfig(userConfig: any, root: string): Promise new URL(addTrailingSlash(val), fileProtocolRoot)), - layouts: z - .string() - .default('./src/layouts') - .transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)), public: z .string() .default('./public') @@ -121,6 +113,11 @@ function addTrailingSlash(str: string): string { /** Convert the generic "yargs" flag object into our own, custom TypeScript object. */ function resolveFlags(flags: Partial): CLIFlags { + if(flags.experimentalStaticBuild) { + // eslint-disable-next-line no-console + console.warn(`Passing --experimental-static-build is no longer necessary and is now the default. The flag will be removed in a future version of Astro.`) + } + return { projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot : undefined, site: typeof flags.site === 'string' ? flags.site : undefined, @@ -128,7 +125,8 @@ function resolveFlags(flags: Partial): CLIFlags { port: typeof flags.port === 'number' ? flags.port : undefined, config: typeof flags.config === 'string' ? flags.config : undefined, hostname: typeof flags.hostname === 'string' ? flags.hostname : undefined, - experimentalStaticBuild: typeof flags.experimentalStaticBuild === 'boolean' ? flags.experimentalStaticBuild : false, + legacyBuild: typeof flags.legacyBuild === 'boolean' ? flags.legacyBuild : false, + experimentalStaticBuild: typeof flags.experimentalStaticBuild === 'boolean' ? flags.experimentalStaticBuild : true, experimentalSsr: typeof flags.experimentalSsr === 'boolean' ? flags.experimentalSsr : false, drafts: typeof flags.drafts === 'boolean' ? flags.drafts : false, }; @@ -147,6 +145,7 @@ function mergeCLIFlags(astroConfig: AstroUserConfig, flags: CLIFlags) { astroConfig.buildOptions.experimentalSsr = flags.experimentalSsr; if (flags.experimentalSsr) { astroConfig.buildOptions.experimentalStaticBuild = true; + astroConfig.buildOptions.legacyBuild = false; } } if (typeof flags.drafts === 'boolean') astroConfig.buildOptions.drafts = flags.drafts; diff --git a/packages/astro/src/core/preview/index.ts b/packages/astro/src/core/preview/index.ts index d53fe837a6..aeafb9bc2f 100644 --- a/packages/astro/src/core/preview/index.ts +++ b/packages/astro/src/core/preview/index.ts @@ -2,17 +2,15 @@ import type { AstroConfig } from '../../@types/astro'; import type { LogOptions } from '../logger'; import type { Stats } from 'fs'; import type { AddressInfo } from 'net'; - import http from 'http'; +import sirv from 'sirv'; import { performance } from 'perf_hooks'; -import send from 'send'; import { fileURLToPath } from 'url'; -import fs from 'fs'; import * as msg from '../messages.js'; import { error, info } from '../logger.js'; -import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js'; import { appendForwardSlash, trimSlashes } from '../path.js'; import { getLocalAddress } from '../dev/util.js'; +import { subpathNotUsedTemplate, notFoundTemplate } from '../../template/4xx.js'; interface PreviewOptions { logging: LogOptions; @@ -25,28 +23,19 @@ export interface PreviewServer { stop(): Promise; } +const HAS_FILE_EXTENSION_REGEXP = /^.*\.[^\\]+$/; + /** The primary dev action */ export default async function preview(config: AstroConfig, { logging }: PreviewOptions): Promise { const startServerTime = performance.now(); - const pageUrlFormat = config.buildOptions.pageUrlFormat; - const trailingSlash = config.devOptions.trailingSlash; - const forceTrailingSlash = trailingSlash === 'always'; - const blockTrailingSlash = trailingSlash === 'never'; - - /** Default file served from a directory. */ - const defaultFile = 'index.html'; - const defaultOrigin = 'http://localhost'; - - const sendOptions = { - extensions: pageUrlFormat === 'file' ? ['html'] : false, - index: false, - root: fileURLToPath(config.dist), - }; - + const trailingSlash = config.devOptions.trailingSlash /** Base request URL. */ let baseURL = new URL(config.buildOptions.site || '/', defaultOrigin); - + const staticFileServer = sirv(fileURLToPath(config.dist), { + etag: true, + maxAge: 0, + }) // Create the preview server, send static files out of the `dist/` directory. const server = http.createServer((req, res) => { const requestURL = new URL(req.url as string, defaultOrigin); @@ -64,55 +53,25 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO const isRoot = pathname === '/'; const hasTrailingSlash = isRoot || pathname.endsWith('/'); - let tryTrailingSlash = true; - let tryHtmlExtension = true; - - let url: URL; - - const onErr = (message: string) => { + function sendError(message: string) { res.statusCode = 404; res.end(notFoundTemplate(pathname, message)); }; - const onStat = (err: NodeJS.ErrnoException | null, stat: Stats) => { - switch (true) { - // retry nonexistent paths without an html extension - case err && tryHtmlExtension && hasTrailingSlash && !blockTrailingSlash: - case err && tryHtmlExtension && !hasTrailingSlash && !forceTrailingSlash && !pathname.endsWith('.html'): - tryHtmlExtension = false; - return fs.stat((url = new URL(url.pathname + '.html', url)), onStat); - - // 404 on nonexistent paths (that are yet handled) - case err !== null: - return onErr('Path not found'); - - // 404 on directories when a trailing slash is present but blocked - case stat.isDirectory() && hasTrailingSlash && blockTrailingSlash && !isRoot: - return onErr('Prohibited trailing slash'); - - // 404 on directories when a trailing slash is missing but forced - case stat.isDirectory() && !hasTrailingSlash && forceTrailingSlash && !isRoot: - return onErr('Required trailing slash'); - - // retry on directories when a default file is missing but allowed (that are yet handled) - case stat.isDirectory() && tryTrailingSlash: - tryTrailingSlash = false; - return fs.stat((url = new URL(url.pathname + (url.pathname.endsWith('/') ? defaultFile : '/' + defaultFile), url)), onStat); - - // 404 on existent directories (that are yet handled) - case stat.isDirectory(): - return onErr('Path not found'); - - // handle existent paths - default: - send(req, fileURLToPath(url), { - extensions: false, - index: false, - }).pipe(res); + switch (true) { + case hasTrailingSlash && trailingSlash == 'never' && !isRoot: + sendError('Not Found (devOptions.trailingSlash is set to "never")'); + return; + case !hasTrailingSlash && trailingSlash == 'always' && !isRoot && !HAS_FILE_EXTENSION_REGEXP.test(pathname): + sendError('Not Found (devOptions.trailingSlash is set to "always")'); + return; + default: { + // HACK: rewrite req.url so that sirv finds the file + req.url = '/' + req.url?.replace(baseURL.pathname, '') + staticFileServer(req, res, () => sendError('Not Found')); + return; } - }; - - fs.stat((url = new URL(trimSlashes(pathname), config.dist)), onStat); + } }); let { hostname, port } = config.devOptions; @@ -165,7 +124,9 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO port, server: httpServer!, stop: async () => { - httpServer.close(); + await new Promise((resolve, reject) => { + httpServer.close((err) => err ? reject(err) : resolve(undefined)); + }); }, }; } diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index 72876b6903..ba13defb15 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -1,7 +1,7 @@ import type { ComponentInstance, EndpointHandler, MarkdownRenderOptions, Params, Props, Renderer, RouteData, SSRElement } from '../../@types/astro'; import type { LogOptions } from '../logger.js'; -import { renderEndpoint, renderPage } from '../../runtime/server/index.js'; +import { renderEndpoint, renderHead, renderToString } from '../../runtime/server/index.js'; import { getParams } from '../routing/index.js'; import { createResult } from './result.js'; import { findPathItemByKey, RouteCache, callGetStaticPaths } from './route-cache.js'; @@ -50,7 +50,7 @@ async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise<[Param } interface RenderOptions { - experimentalStaticBuild: boolean; + legacyBuild: boolean; logging: LogOptions; links: Set; markdownRender: MarkdownRenderOptions; @@ -66,7 +66,7 @@ interface RenderOptions { } export async function render(opts: RenderOptions): Promise { - const { experimentalStaticBuild, links, logging, origin, markdownRender, mod, pathname, scripts, renderers, resolve, route, routeCache, site } = opts; + const { legacyBuild, links, logging, origin, markdownRender, mod, pathname, scripts, renderers, resolve, route, routeCache, site } = opts; const [params, pageProps] = await getParamsAndProps({ logging, @@ -87,7 +87,7 @@ export async function render(opts: RenderOptions): Promise { if (!Component.isAstroComponentFactory) throw new Error(`Unable to SSR non-Astro component (${route?.component})`); const result = createResult({ - experimentalStaticBuild, + legacyBuild, links, logging, markdownRender, @@ -100,10 +100,17 @@ export async function render(opts: RenderOptions): Promise { scripts, }); - let html = await renderPage(result, Component, pageProps, null); + let html = await renderToString(result, Component, pageProps, null); + + // handle final head injection if it hasn't happened already + if (html.indexOf("") == -1) { + html = await renderHead(result) + html; + } + // cleanup internal state flags + html = html.replace("", ''); // inject if missing (TODO: is a more robust check needed for comments, etc.?) - if (experimentalStaticBuild && !/\n' + html; } diff --git a/packages/astro/src/core/render/dev/index.ts b/packages/astro/src/core/render/dev/index.ts index c4c7690590..9f792d58ed 100644 --- a/packages/astro/src/core/render/dev/index.ts +++ b/packages/astro/src/core/render/dev/index.ts @@ -1,5 +1,5 @@ import type * as vite from 'vite'; -import type { AstroConfig, ComponentInstance, Renderer, RouteData, RuntimeMode } from '../../../@types/astro'; +import type { AstroConfig, ComponentInstance, Renderer, RouteData, RuntimeMode, SSRElement } from '../../../@types/astro'; import { LogOptions } from '../../logger.js'; import { fileURLToPath } from 'url'; import { getStylesForURL } from './css.js'; @@ -48,14 +48,15 @@ export async function preload({ astroConfig, filePath, viteServer }: SSROptions) /** use Vite to SSR */ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrOpts: SSROptions): Promise { const { astroConfig, filePath, logging, mode, origin, pathname, route, routeCache, viteServer } = ssrOpts; + const legacy = astroConfig.buildOptions.legacyBuild; // Add hoisted script tags const scripts = createModuleScriptElementWithSrcSet( - astroConfig.buildOptions.experimentalStaticBuild && mod.hasOwnProperty('$$metadata') ? Array.from(mod.$$metadata.hoistedScriptPaths()) : [] + !legacy && mod.hasOwnProperty('$$metadata') ? Array.from(mod.$$metadata.hoistedScriptPaths()) : [] ); // Inject HMR scripts - if (mod.hasOwnProperty('$$metadata') && mode === 'development' && astroConfig.buildOptions.experimentalStaticBuild) { + if (mod.hasOwnProperty('$$metadata') && mode === 'development' && !legacy) { scripts.add({ props: { type: 'module', src: '/@vite/client' }, children: '', @@ -66,9 +67,31 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO }); } + // Pass framework CSS in as link tags to be appended to the page. + let links = new Set(); + if(!legacy) { + [...getStylesForURL(filePath, viteServer)].forEach((href) => { + if (mode === 'development' && svelteStylesRE.test(href)) { + scripts.add({ + props: { type: 'module', src: href }, + children: '', + }); + } else { + links.add({ + props: { + rel: 'stylesheet', + href, + 'data-astro-injected': true, + }, + children: '', + }); + } + }); + } + let content = await coreRender({ - experimentalStaticBuild: astroConfig.buildOptions.experimentalStaticBuild, - links: new Set(), + legacyBuild: astroConfig.buildOptions.legacyBuild, + links, logging, markdownRender: astroConfig.markdownOptions.render, mod, @@ -80,7 +103,7 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO // The legacy build needs these to remain unresolved so that vite HTML // Can do the resolution. Without this condition the build output will be // broken in the legacy build. This can be removed once the legacy build is removed. - if (astroConfig.buildOptions.experimentalStaticBuild) { + if (!astroConfig.buildOptions.legacyBuild) { const [, resolvedPath] = await viteServer.moduleGraph.resolveUrl(s); return resolvedPath; } else { @@ -101,7 +124,7 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO const tags: vite.HtmlTagDescriptor[] = []; // dev only: inject Astro HMR client - if (mode === 'development' && !astroConfig.buildOptions.experimentalStaticBuild) { + if (mode === 'development' && legacy) { tags.push({ tag: 'script', attrs: { type: 'module' }, @@ -113,31 +136,34 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO } // inject CSS - [...getStylesForURL(filePath, viteServer)].forEach((href) => { - if (mode === 'development' && svelteStylesRE.test(href)) { - tags.push({ - tag: 'script', - attrs: { type: 'module', src: href }, - injectTo: 'head', - }); - } else { - tags.push({ - tag: 'link', - attrs: { - rel: 'stylesheet', - href, - 'data-astro-injected': true, - }, - injectTo: 'head', - }); - } - }); + if(legacy) { + [...getStylesForURL(filePath, viteServer)].forEach((href) => { + if (mode === 'development' && svelteStylesRE.test(href)) { + tags.push({ + tag: 'script', + attrs: { type: 'module', src: href }, + injectTo: 'head', + }); + } else { + tags.push({ + tag: 'link', + attrs: { + rel: 'stylesheet', + href, + 'data-astro-injected': true, + }, + injectTo: 'head', + }); + } + }); + } + // add injected tags content = injectTags(content, tags); // run transformIndexHtml() in dev to run Vite dev transformations - if (mode === 'development' && !astroConfig.buildOptions.experimentalStaticBuild) { + if (mode === 'development' && astroConfig.buildOptions.legacyBuild) { const relativeURL = filePath.href.replace(astroConfig.projectRoot.href, '/'); content = await viteServer.transformIndexHtml(relativeURL, content, pathname); } diff --git a/packages/astro/src/core/render/result.ts b/packages/astro/src/core/render/result.ts index d0a186df51..ec696a2868 100644 --- a/packages/astro/src/core/render/result.ts +++ b/packages/astro/src/core/render/result.ts @@ -8,7 +8,7 @@ import { renderSlot } from '../../runtime/server/index.js'; import { warn, LogOptions } from '../logger.js'; export interface CreateResultArgs { - experimentalStaticBuild: boolean; + legacyBuild: boolean; logging: LogOptions; origin: string; markdownRender: MarkdownRenderOptions; @@ -22,7 +22,7 @@ export interface CreateResultArgs { } export function createResult(args: CreateResultArgs): SSRResult { - const { experimentalStaticBuild, origin, markdownRender, params, pathname, renderers, resolve, site: buildOptionsSite } = args; + const { legacyBuild, origin, markdownRender, params, pathname, renderers, resolve, site: buildOptionsSite } = args; // Create the result object that will be passed into the render function. // This object starts here as an empty shell (not yet the result) but then @@ -45,7 +45,7 @@ export function createResult(args: CreateResultArgs): SSRResult { url, }, resolve(path: string) { - if (experimentalStaticBuild) { + if (!legacyBuild) { let extra = `This can be replaced with a dynamic import like so: await import("${path}")`; if (isCSSRequest(path)) { extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this: @@ -116,7 +116,7 @@ ${extra}` _metadata: { renderers, pathname, - experimentalStaticBuild, + legacyBuild }, }; diff --git a/packages/astro/src/core/render/sitemap.ts b/packages/astro/src/core/render/sitemap.ts index a5ef54f6a7..4f695253d4 100644 --- a/packages/astro/src/core/render/sitemap.ts +++ b/packages/astro/src/core/render/sitemap.ts @@ -3,7 +3,6 @@ const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/; /** Construct sitemap.xml given a set of URLs */ export function generateSitemap(pages: string[]): string { // TODO: find way to respect URLs here - // TODO: find way to exclude pages from sitemap // copy just in case original copy is needed diff --git a/packages/astro/src/core/routing/manifest/create.ts b/packages/astro/src/core/routing/manifest/create.ts index 909ddd1a55..1e0a6f3bc0 100644 --- a/packages/astro/src/core/routing/manifest/create.ts +++ b/packages/astro/src/core/routing/manifest/create.ts @@ -216,7 +216,7 @@ export function createRouteManifest({ config, cwd }: { config: AstroConfig; cwd? basename, ext, parts, - file: slash(file), + file: file.replace(/\\/g, '/'), isDir, isIndex, isPage, diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 52d19fd872..625c762dec 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -71,7 +71,7 @@ export class AstroComponent { const html = htmlParts[i]; const expression = expressions[i]; - yield _render(unescapeHTML(html)); + yield unescapeHTML(html); yield _render(expression); } } @@ -337,12 +337,14 @@ export function createAstro(filePathname: string, _site: string, projectRootStr: }; } -const toAttributeString = (value: any) => String(value).replace(/&/g, '&').replace(/"/g, '"'); +const toAttributeString = (value: any, shouldEscape = true) => shouldEscape ? + String(value).replace(/&/g, '&').replace(/"/g, '"') : + value; const STATIC_DIRECTIVES = new Set(['set:html', 'set:text']); // A helper used to turn expressions into attribute key/value -export function addAttribute(value: any, key: string) { +export function addAttribute(value: any, key: string, shouldEscape = true) { if (value == null) { return ''; } @@ -372,15 +374,15 @@ Make sure to use the static attribute syntax (\`${key}={value}\`) instead of the if (value === true && (key.startsWith('data-') || htmlBooleanAttributes.test(key))) { return unescapeHTML(` ${key}`); } else { - return unescapeHTML(` ${key}="${toAttributeString(value)}"`); + return unescapeHTML(` ${key}="${toAttributeString(value, shouldEscape)}"`); } } // Adds support for ` -export function spreadAttributes(values: Record) { +export function spreadAttributes(values: Record, shouldEscape = true) { let output = ''; for (const [key, value] of Object.entries(values)) { - output += addAttribute(value, key); + output += addAttribute(value, key, shouldEscape); } return unescapeHTML(output); } @@ -403,20 +405,6 @@ export function defineScriptVars(vars: Record) { return output; } -// Calls a component and renders it into a string of HTML -export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any) { - const Component = await componentFactory(result, props, children); - let template = await renderAstroComponent(Component); - return unescapeHTML(template); -} - -// Filter out duplicate elements in our set -const uniqueElements = (item: any, index: number, all: any[]) => { - const props = JSON.stringify(item.props); - const children = item.children; - return index === all.findIndex((i) => JSON.stringify(i.props) === props && i.children == children); -}; - // Renders an endpoint request to completion, returning the body. export async function renderEndpoint(mod: EndpointHandler, params: any) { const method = 'get'; @@ -431,15 +419,34 @@ export async function renderEndpoint(mod: EndpointHandler, params: any) { return body; } +// Calls a component and renders it into a string of HTML +export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any) { + const Component = await componentFactory(result, props, children); + let template = await renderAstroComponent(Component); + + // injected by compiler + // Must be handled at the end of the rendering process + if (template.indexOf('') > -1) { + template = template.replace('', await renderHead(result)); + } + return template; +} + +// Filter out duplicate elements in our set +const uniqueElements = (item: any, index: number, all: any[]) => { + const props = JSON.stringify(item.props); + const children = item.children; + return index === all.findIndex((i) => JSON.stringify(i.props) === props && i.children == children); +}; + + // Renders a page to completion by first calling the factory callback, waiting for its result, and then appending // styles and scripts into the head. -export async function renderPage(result: SSRResult, Component: AstroComponentFactory, props: any, children: any) { - const template = await renderToString(result, Component, props, children); +export async function renderHead(result: SSRResult) { const styles = Array.from(result.styles) .filter(uniqueElements) .map((style) => { - const styleChildren = result._metadata.experimentalStaticBuild ? '' : style.children; - + const styleChildren = !result._metadata.legacyBuild ? '' : style.children; return renderElement('style', { children: styleChildren, props: { ...style.props, 'astro-style': true }, @@ -460,17 +467,10 @@ export async function renderPage(result: SSRResult, Component: AstroComponentFac if (needsHydrationStyles) { styles.push(renderElement('style', { props: { 'astro-style': true }, children: 'astro-root, astro-fragment { display: contents; }' })); } - const links = Array.from(result.links) .filter(uniqueElements) - .map((link) => renderElement('link', link)); - - // inject styles & scripts at end of - let headPos = template.indexOf(''); - if (headPos === -1) { - return links.join('\n') + styles.join('\n') + scripts.join('\n') + template; // if no , prepend styles & scripts - } - return template.substring(0, headPos) + links.join('\n') + styles.join('\n') + scripts.join('\n') + template.substring(headPos); + .map((link) => renderElement('link', link, false)); + return unescapeHTML(links.join('\n') + styles.join('\n') + scripts.join('\n') + '\n' + ''); } export async function renderAstroComponent(component: InstanceType) { @@ -513,7 +513,7 @@ function getHTMLElementName(constructor: typeof HTMLElement) { return assignedName; } -function renderElement(name: string, { props: _props, children = '' }: SSRElement) { +function renderElement(name: string, { props: _props, children = '' }: SSRElement, shouldEscape = true) { // Do not print `hoist`, `lang`, `global` const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props; if (defineVars) { @@ -530,5 +530,5 @@ function renderElement(name: string, { props: _props, children = '' }: SSRElemen children = defineScriptVars(defineVars) + '\n' + children; } } - return `<${name}${spreadAttributes(props)}>${children}`; + return `<${name}${spreadAttributes(props, shouldEscape)}>${children}`; } diff --git a/packages/astro/src/runtime/server/metadata.ts b/packages/astro/src/runtime/server/metadata.ts index 5343c03017..9fb23724d1 100644 --- a/packages/astro/src/runtime/server/metadata.ts +++ b/packages/astro/src/runtime/server/metadata.ts @@ -13,6 +13,7 @@ interface ComponentMetadata { interface CreateMetadataOptions { modules: ModuleInfo[]; hydratedComponents: any[]; + clientOnlyComponents: any[]; hydrationDirectives: Set; hoisted: any[]; } @@ -22,6 +23,7 @@ export class Metadata { public modules: ModuleInfo[]; public hoisted: any[]; public hydratedComponents: any[]; + public clientOnlyComponents: any[]; public hydrationDirectives: Set; private metadataCache: Map; @@ -30,6 +32,7 @@ export class Metadata { this.modules = opts.modules; this.hoisted = opts.hoisted; this.hydratedComponents = opts.hydratedComponents; + this.clientOnlyComponents = opts.clientOnlyComponents; this.hydrationDirectives = opts.hydrationDirectives; this.mockURL = new URL(filePathname, 'http://example.com'); this.metadataCache = new Map(); @@ -66,6 +69,19 @@ export class Metadata { } } + *clientOnlyComponentPaths() { + const found = new Set(); + for (const metadata of this.deepMetadata()) { + for (const component of metadata.clientOnlyComponents) { + const path = metadata.resolvePath(component); + if (path && !found.has(path)) { + found.add(path); + yield path; + } + } + } + } + /** * Gets all of the hydration specifiers used within this component. */ diff --git a/packages/astro/src/vite-plugin-astro/compile.ts b/packages/astro/src/vite-plugin-astro/compile.ts index 91e38f7054..4385d94682 100644 --- a/packages/astro/src/vite-plugin-astro/compile.ts +++ b/packages/astro/src/vite-plugin-astro/compile.ts @@ -33,11 +33,8 @@ function safelyReplaceImportPlaceholder(code: string) { const configCache = new WeakMap(); async function compile(config: AstroConfig, filename: string, source: string, viteTransform: TransformHook, opts: { ssr: boolean }): Promise { - // pages and layouts should be transformed as full documents (implicit etc) - // everything else is treated as a fragment const filenameURL = new URL(`file://${filename}`); const normalizedID = fileURLToPath(filenameURL); - const isPage = normalizedID.startsWith(fileURLToPath(config.pages)) || normalizedID.startsWith(fileURLToPath(config.layouts)); const pathname = filenameURL.pathname.substr(config.projectRoot.pathname.length - 1); let rawCSSDeps = new Set(); @@ -47,22 +44,21 @@ async function compile(config: AstroConfig, filename: string, source: string, vi // use `sourcemap: "both"` so that sourcemap is included in the code // result passed to esbuild, but also available in the catch handler. const transformResult = await transform(source, { - as: isPage ? 'document' : 'fragment', pathname, projectRoot: config.projectRoot.toString(), site: config.buildOptions.site, sourcefile: filename, sourcemap: 'both', internalURL: `/@fs${new URL('../runtime/server/index.js', import.meta.url).pathname}`, - experimentalStaticExtraction: config.buildOptions.experimentalStaticBuild, + experimentalStaticExtraction: !config.buildOptions.legacyBuild, // TODO add experimental flag here preprocessStyle: async (value: string, attrs: Record) => { const lang = `.${attrs?.lang || 'css'}`.toLowerCase(); try { // In the static build, grab any @import as CSS dependencies for HMR. - if (config.buildOptions.experimentalStaticBuild) { - value = value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => { + if (!config.buildOptions.legacyBuild) { + value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => { rawCSSDeps.add(spec); // If the language is CSS: prevent `@import` inlining to prevent scoping of imports. // Otherwise: Sass, etc. need to see imports for variables, so leave in for their compiler to handle. diff --git a/packages/astro/src/vite-plugin-env/index.ts b/packages/astro/src/vite-plugin-env/index.ts index c216b71118..36a9835b1f 100644 --- a/packages/astro/src/vite-plugin-env/index.ts +++ b/packages/astro/src/vite-plugin-env/index.ts @@ -1,5 +1,6 @@ import type * as vite from 'vite'; import type { AstroConfig } from '../@types/astro'; +import type { TransformPluginContext } from 'rollup'; import MagicString from 'magic-string'; import { fileURLToPath } from 'url'; import { loadEnv } from 'vite'; @@ -30,7 +31,7 @@ function getPrivateEnv(viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig if (privateKeys.length === 0) { return null; } - return Object.fromEntries(privateKeys.map((key) => [key, fullEnv[key]])); + return Object.fromEntries(privateKeys.map((key) => [key, JSON.stringify(fullEnv[key])])); } function referencesPrivateKey(source: string, privateEnv: Record) { @@ -43,39 +44,56 @@ function referencesPrivateKey(source: string, privateEnv: Record) { export default function envVitePlugin({ config: astroConfig }: EnvPluginOptions): vite.PluginOption { let privateEnv: Record | null; let config: vite.ResolvedConfig; + let replacements: Record; + let pattern: RegExp | undefined; return { name: 'astro:vite-plugin-env', enforce: 'pre', - configResolved(resolvedConfig) { config = resolvedConfig; - if (config.envPrefix) { - } }, - async transform(source, id, options) { const ssr = options?.ssr === true; - if (!ssr) return source; - if (!source.includes('import.meta')) return source; - if (!/\benv\b/.test(source)) return source; + + if(!ssr) { + return source; + } + + if(!source.includes('import.meta') || !/\benv\b/.test(source)) { + return source; + } if (typeof privateEnv === 'undefined') { privateEnv = getPrivateEnv(config, astroConfig); + if(privateEnv) { + const entries = Object.entries(privateEnv).map(([key, value]) => ([`import.meta.env.${key}`, value])); + replacements = Object.fromEntries(entries); + pattern = new RegExp( + // Do not allow preceding '.', but do allow preceding '...' for spread operations + '(? { + return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); + }) + .join('|') + + // prevent trailing assignments + ')\\b(?!\\s*?=[^=])', 'g'); + } } - if (!privateEnv) return source; + + if (!privateEnv || !pattern) return source; if (!referencesPrivateKey(source, privateEnv)) return source; + // Find matches for *private* env and do our own replacement. const s = new MagicString(source); - // prettier-ignore - s.prepend(`import.meta.env = new Proxy(import.meta.env, {` + - `get(target, prop, reciever) {` + - `const PRIVATE = ${JSON.stringify(privateEnv)};` + - `if (typeof PRIVATE[prop] !== 'undefined') {` + - `return PRIVATE[prop];` + - `}` + - `return Reflect.get(target, prop, reciever);` + - `}` + - `});\n`); + let match: RegExpExecArray | null + + while ((match = pattern.exec(source))) { + const start = match.index + const end = start + match[0].length + const replacement = '' + replacements[match[1]] + s.overwrite(start, end, replacement) + } return s.toString(); }, diff --git a/packages/astro/test/0-css.test.js b/packages/astro/test/0-css.test.js index 1ca8acf2e1..6e8629c954 100644 --- a/packages/astro/test/0-css.test.js +++ b/packages/astro/test/0-css.test.js @@ -15,12 +15,17 @@ describe('CSS', function () { fixture = await loadFixture({ projectRoot: './fixtures/0-css/', renderers: ['@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'], + vite: { + build: { + assetsInlineLimit: 0 + } + } }); }); // test HTML and CSS contents for accuracy describe('build', () => { - this.timeout(30000); // test needs a little more time in CI + this.timeout(45000); // test needs a little more time in CI let $; let bundledCSS; @@ -31,7 +36,7 @@ describe('CSS', function () { // get bundled CSS (will be hashed, hence DOM query) const html = await fixture.readFile('/index.html'); $ = cheerio.load(html); - const bundledCSSHREF = $('link[rel=stylesheet][href^=./assets/]').attr('href'); + const bundledCSSHREF = $('link[rel=stylesheet][href^=/assets/]').attr('href'); bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/')); }); @@ -47,7 +52,8 @@ describe('CSS', function () { expect(el2.attr('class')).to.equal(`visible ${scopedClass}`); // 2. check CSS - expect(bundledCSS).to.include(`.blue.${scopedClass}{color:#b0e0e6}.color\\:blue.${scopedClass}{color:#b0e0e6}.visible.${scopedClass}{display:block}`); + const expected = `.blue.${scopedClass}{color:#b0e0e6}.color\\\\:blue.${scopedClass}{color:#b0e0e6}.visible.${scopedClass}{display:block}`; + expect(bundledCSS).to.include(expected); }); it('No - - - - + + +
diff --git a/packages/astro/test/fixtures/astro-assets/src/pages/index.astro b/packages/astro/test/fixtures/astro-assets/src/pages/index.astro index b509f3fb95..341f2744c5 100644 --- a/packages/astro/test/fixtures/astro-assets/src/pages/index.astro +++ b/packages/astro/test/fixtures/astro-assets/src/pages/index.astro @@ -9,7 +9,7 @@ import p2Url from '../images/penguin2.jpg?url';

Icons

- + - - - - - diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/layouts/PageLayout.astro b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/layouts/PageLayout.astro deleted file mode 100644 index b1b4514ca0..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/layouts/PageLayout.astro +++ /dev/null @@ -1,12 +0,0 @@ ---- -import BaseLayout from "./BaseLayout.astro" -import "../styles/page-one.css" - -const {title} = Astro.props; ---- - - -
- -
-
diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-1.astro b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-1.astro deleted file mode 100644 index 1d2ca244a5..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-1.astro +++ /dev/null @@ -1,15 +0,0 @@ ---- - import PageLayout from "../layouts/PageLayout.astro" - - const date = new Date(); ---- - - -

Page 1

-

This page has styling in dev-server. But the built page has no styling.

-

Check dist/page-1/index.html. There are no stylesheets imported.

-

Additionally, there is an empty js file in the dist/assets folder. Thankfully the file is not required by any page.

-

Execute the build npm run build and preview it npx http-server dist/ at https://github-qoihup--8080.local.webcontainer.io/page-1/

- -

Date: {date}

-
diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-2.astro b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-2.astro deleted file mode 100644 index 5932f9444a..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/pages/page-2.astro +++ /dev/null @@ -1,9 +0,0 @@ ---- - import PageLayout from "../layouts/PageLayout.astro" - import "../styles/page-two.css" ---- - - -

Page 2

-

Nothing to see here. Check Page 1

-
diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-one.css b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-one.css deleted file mode 100644 index ce7da04630..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-one.css +++ /dev/null @@ -1,3 +0,0 @@ -p { - color: blue; -} diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-two.css b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-two.css deleted file mode 100644 index 87002430ab..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/page-two.css +++ /dev/null @@ -1,3 +0,0 @@ -p { - color: green; -} diff --git a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/site.css b/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/site.css deleted file mode 100644 index 47a8192ee5..0000000000 --- a/packages/astro/test/fixtures/astro-css-bundling-nested-layouts/src/styles/site.css +++ /dev/null @@ -1,7 +0,0 @@ -p { - color: red; -} - -h1 { - outline: 1px solid red; -} diff --git a/packages/astro/test/fixtures/astro-css-bundling/src/pages/index.astro b/packages/astro/test/fixtures/astro-css-bundling/src/pages/index.astro index f776de2e86..0187ef6ea1 100644 --- a/packages/astro/test/fixtures/astro-css-bundling/src/pages/index.astro +++ b/packages/astro/test/fixtures/astro-css-bundling/src/pages/index.astro @@ -4,9 +4,11 @@ import Nav from '../components/Nav.astro'; - - - +