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 <natemoo-re@users.noreply.github.com> * 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 <evan@boehs.org> * 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] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Nate Moore <nate@skypack.dev> * 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 <matthew@skypack.dev> Co-authored-by: Evan Boehs <evan@boehs.org> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Fred K. Schott <fkschott@gmail.com>
This commit is contained in:
parent
c139829b10
commit
72c2c86e9d
130 changed files with 2439 additions and 2455 deletions
5
.changeset/five-stingrays-collect.md
Normal file
5
.changeset/five-stingrays-collect.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes the static build to write to 404.html
|
5
.changeset/fresh-ladybugs-think.md
Normal file
5
.changeset/fresh-ladybugs-think.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes use of private .env variables with the static build
|
19
.changeset/modern-elephants-burn.md
Normal file
19
.changeset/modern-elephants-burn.md
Normal file
|
@ -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.
|
7
.changeset/new-pianos-boil.md
Normal file
7
.changeset/new-pianos-boil.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
'astro': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
## Updated `<head>` and `<body>` behavior
|
||||||
|
|
||||||
|
Since `astro@0.21`, Astro placed certain restrictions on what files could use `<head>` or `<body>` tags. In `astro@0.24`, the restrictions have been lifted. Astro will be able to correctly handle `<head>` and `<body>` tags in _any_ component, not just those in `src/pages/` or `src/layouts/`.
|
57
.changeset/pre.json
Normal file
57
.changeset/pre.json
Normal file
|
@ -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"
|
||||||
|
]
|
||||||
|
}
|
5
.changeset/thick-ravens-chew.md
Normal file
5
.changeset/thick-ravens-chew.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Replace `send` dependency with `sirv`
|
32
.npmrc
32
.npmrc
|
@ -3,19 +3,19 @@ prefer-workspace-packages=true
|
||||||
link-workspace-packages=true
|
link-workspace-packages=true
|
||||||
save-workspace-protocol=false # This prevents the examples to have the `workspace:` prefix
|
save-workspace-protocol=false # This prevents the examples to have the `workspace:` prefix
|
||||||
|
|
||||||
use-node-version=14.19.0
|
shamefully-hoist=true
|
||||||
|
# TODO: We would like to move to individual opt-in hoisting, but Astro was not originally
|
||||||
# Rather than shamefully hoisting everything, just make problematic packages public
|
# written with this in mind. In the future, it would be good to hoist individual packages only.
|
||||||
public-hoist-pattern[]=autoprefixer
|
# public-hoist-pattern[]=autoprefixer
|
||||||
public-hoist-pattern[]=astro
|
# public-hoist-pattern[]=astro
|
||||||
public-hoist-pattern[]=remark-*
|
# public-hoist-pattern[]=remark-*
|
||||||
public-hoist-pattern[]=rehype-*
|
# public-hoist-pattern[]=rehype-*
|
||||||
public-hoist-pattern[]=react
|
# public-hoist-pattern[]=react
|
||||||
public-hoist-pattern[]=react-dom
|
# public-hoist-pattern[]=react-dom
|
||||||
public-hoist-pattern[]=preact
|
# public-hoist-pattern[]=preact
|
||||||
public-hoist-pattern[]=preact-render-to-string
|
# public-hoist-pattern[]=preact-render-to-string
|
||||||
public-hoist-pattern[]=vue
|
# public-hoist-pattern[]=vue
|
||||||
public-hoist-pattern[]=svelte
|
# public-hoist-pattern[]=svelte
|
||||||
public-hoist-pattern[]=solid-js
|
# public-hoist-pattern[]=solid-js
|
||||||
public-hoist-pattern[]=lit
|
# public-hoist-pattern[]=lit
|
||||||
public-hoist-pattern[]=@webcomponents/template-shadowroot
|
# public-hoist-pattern[]=@webcomponents/template-shadowroot
|
||||||
|
|
0
comp.txt
0
comp.txt
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7",
|
"astro": "^0.24.0-next.0",
|
||||||
"sass": "^1.49.8"
|
"sass": "^1.49.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7",
|
"astro": "^0.24.0-next.0",
|
||||||
"@astrojs/renderer-preact": "^0.5.0"
|
"@astrojs/renderer-preact": "^0.5.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7",
|
"@example/my-component": "workspace:*",
|
||||||
"@example/my-component": "workspace:*"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
"serve": "astro --project-root demo preview"
|
"serve": "astro --project-root demo preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,12 +9,16 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@algolia/client-search": "^4.12.0",
|
||||||
"@docsearch/css": "^3.0.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": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-react": "^0.5.0",
|
"@astrojs/renderer-react": "^0.5.0",
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,7 @@ export default function Search() {
|
||||||
initialScrollY={window.scrollY}
|
initialScrollY={window.scrollY}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
indexName={(CONFIG as any).ALGOLIA.indexName}
|
indexName={(CONFIG as any).ALGOLIA.indexName}
|
||||||
|
appId={(CONFIG as any).ALGOLIA.appId}
|
||||||
apiKey={(CONFIG as any).ALGOLIA.apiKey}
|
apiKey={(CONFIG as any).ALGOLIA.apiKey}
|
||||||
transformItems={(items) => {
|
transformItems={(items) => {
|
||||||
return items.map((item) => {
|
return items.map((item) => {
|
||||||
|
|
|
@ -26,6 +26,7 @@ export const KNOWN_LANGUAGES = {
|
||||||
// See "Algolia" section of the README for more information.
|
// See "Algolia" section of the README for more information.
|
||||||
// export const ALGOLIA = {
|
// export const ALGOLIA = {
|
||||||
// indexName: 'XXXXXXXXXX',
|
// indexName: 'XXXXXXXXXX',
|
||||||
|
// appId: 'XXXXXXXXXX',
|
||||||
// apiKey: 'XXXXXXXXXX',
|
// apiKey: 'XXXXXXXXXX',
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-vue": "^0.4.0",
|
"@astrojs/renderer-vue": "^0.4.0",
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7",
|
|
||||||
"sass": "^1.49.8",
|
"sass": "^1.49.8",
|
||||||
|
"astro": "^0.24.0-next.0",
|
||||||
|
"preact": "~10.6.5",
|
||||||
"unocss": "^0.15.5",
|
"unocss": "^0.15.5",
|
||||||
"vite-imagetools": "^4.0.1",
|
"vite-imagetools": "^4.0.1"
|
||||||
"@astrojs/renderer-vue": "^0.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-lit": "^0.4.0",
|
"@astrojs/renderer-lit": "^0.4.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"@astrojs/renderer-react": "^0.5.0",
|
"@astrojs/renderer-react": "^0.5.0",
|
||||||
"@astrojs/renderer-solid": "^0.4.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",
|
"@astrojs/renderer-vue": "^0.4.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-react": "^0.5.0",
|
"@astrojs/renderer-react": "^0.5.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-solid": "^0.4.0",
|
"@astrojs/renderer-solid": "^0.4.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-svelte": "^0.4.0",
|
"@astrojs/renderer-svelte": "^0.5.1",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-vue": "^0.4.0",
|
"@astrojs/renderer-vue": "^0.4.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-svelte": "^0.4.0",
|
"@astrojs/renderer-svelte": "^0.5.1",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
"server": "node server/server.mjs"
|
"server": "node server/server.mjs"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-svelte": "^0.4.0",
|
"@astrojs/renderer-svelte": "^0.5.1",
|
||||||
"astro": "^0.23.7",
|
"astro": "^0.24.0-next.0",
|
||||||
"unocss": "^0.15.5",
|
"unocss": "^0.15.5",
|
||||||
"vite-imagetools": "^4.0.1",
|
"vite-imagetools": "^4.0.1"
|
||||||
"@astrojs/renderer-svelte": "^0.5.1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7",
|
"@astrojs/renderer-react": "^0.5.0",
|
||||||
"@astrojs/renderer-react": "^0.5.0"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/markdown-remark": "^0.6.1",
|
"@astrojs/markdown-remark": "^0.6.1",
|
||||||
"astro": "^0.23.7",
|
"astro": "^0.24.0-next.0",
|
||||||
"hast-util-select": "5.0.1",
|
"hast-util-select": "5.0.1",
|
||||||
"rehype-autolink-headings": "^6.1.0",
|
"rehype-autolink-headings": "^6.1.0",
|
||||||
"rehype-slug": "^5.0.0",
|
"rehype-slug": "^5.0.0",
|
||||||
|
|
|
@ -10,6 +10,6 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/markdown-remark": "^0.6.1",
|
"@astrojs/markdown-remark": "^0.6.1",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"@astrojs/renderer-react": "^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/renderer-vue": "^0.4.0",
|
||||||
"@astrojs/markdown-remark": "^0.6.1",
|
"@astrojs/markdown-remark": "^0.6.1",
|
||||||
"astro": "^0.23.7"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,18 +13,18 @@
|
||||||
"@nanostores/react": "^0.1.5",
|
"@nanostores/react": "^0.1.5",
|
||||||
"@nanostores/vue": "^0.4.1",
|
"@nanostores/vue": "^0.4.1",
|
||||||
"nanostores": "^0.5.7",
|
"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": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-react": "^0.5.0",
|
"@astrojs/renderer-react": "^0.5.0",
|
||||||
"@astrojs/renderer-svelte": "^0.4.0",
|
|
||||||
"@astrojs/renderer-vue": "^0.4.0",
|
"@astrojs/renderer-vue": "^0.4.0",
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"@astrojs/renderer-solid": "^0.4.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-svelte": "^0.5.1",
|
||||||
"@astrojs/renderer-vue": "^0.4.0"
|
"astro": "^0.24.0-next.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astrojs/renderer-preact": "^0.5.0",
|
"@astrojs/renderer-preact": "^0.5.0",
|
||||||
"astro": "^0.23.7",
|
"postcss": "^8.3.8",
|
||||||
|
"astro": "^0.24.0-next.0",
|
||||||
"autoprefixer": "^10.4.0",
|
"autoprefixer": "^10.4.0",
|
||||||
"tailwindcss": "^3.0.5",
|
"tailwindcss": "^3.0.5"
|
||||||
"@astrojs/renderer-preact": "^0.5.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
"preview": "astro preview"
|
"preview": "astro preview"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"astro": "^0.23.7",
|
"astro": "^0.24.0-next.0",
|
||||||
"vite-plugin-pwa": "0.11.11",
|
"vite-plugin-pwa": "0.11.11",
|
||||||
"workbox-window": "^6.5.0"
|
"workbox-window": "^6.5.0"
|
||||||
}
|
}
|
||||||
|
|
23
package.json
23
package.json
|
@ -43,7 +43,8 @@
|
||||||
"peerDependencyRules": {
|
"peerDependencyRules": {
|
||||||
"ignoreMissing": [
|
"ignoreMissing": [
|
||||||
"@babel/core",
|
"@babel/core",
|
||||||
"@babel/plugin-transform-react-jsx"
|
"@babel/plugin-transform-react-jsx",
|
||||||
|
"vite"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -51,20 +52,20 @@
|
||||||
"@astrojs/webapi": "workspace:*"
|
"@astrojs/webapi": "workspace:*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@changesets/changelog-github": "^0.4.2",
|
"@changesets/changelog-github": "^0.4.3",
|
||||||
"@changesets/cli": "^2.16.0",
|
"@changesets/cli": "^2.21.1",
|
||||||
"@octokit/action": "^3.15.4",
|
"@octokit/action": "^3.18.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
"@typescript-eslint/eslint-plugin": "^5.14.0",
|
||||||
"@typescript-eslint/parser": "^5.0.0",
|
"@typescript-eslint/parser": "^5.14.0",
|
||||||
"del": "^6.0.0",
|
"del": "^6.0.0",
|
||||||
"esbuild": "0.13.7",
|
"esbuild": "0.13.7",
|
||||||
"eslint": "^8.0.1",
|
"eslint": "^8.10.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"execa": "^6.0.0",
|
"execa": "^6.1.0",
|
||||||
"prettier": "^2.4.1",
|
"prettier": "^2.5.1",
|
||||||
"pretty-bytes": "^6.0.0",
|
"pretty-bytes": "^6.0.0",
|
||||||
"tiny-glob": "^0.2.8",
|
"tiny-glob": "^0.2.9",
|
||||||
"turbo": "^1.1.5",
|
"turbo": "^1.1.5",
|
||||||
"typescript": "4.5.2"
|
"typescript": "4.5.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,35 @@
|
||||||
# astro
|
# 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 `<head>` and `<body>` behavior**
|
||||||
|
|
||||||
|
Since `astro@0.21`, Astro placed certain restrictions on what files could use `<head>` or `<body>` tags. In `astro@0.24`, the restrictions have been lifted. Astro will be able to correctly handle `<head>` and `<body>` 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
|
## 0.23.7
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
@ -96,12 +126,12 @@
|
||||||
```typescript
|
```typescript
|
||||||
// src/pages/company.json.ts
|
// src/pages/company.json.ts
|
||||||
export async function get() {
|
export async function get() {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: 'Astro Technology Company',
|
name: 'Astro Technology Company',
|
||||||
url: 'https://astro.build/',
|
url: 'https://astro.build/',
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -263,12 +293,12 @@
|
||||||
```typescript
|
```typescript
|
||||||
// src/pages/company.json.ts
|
// src/pages/company.json.ts
|
||||||
export async function get() {
|
export async function get() {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
name: 'Astro Technology Company',
|
name: 'Astro Technology Company',
|
||||||
url: 'https://astro.build/',
|
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
|
```js
|
||||||
export default {
|
export default {
|
||||||
markdownOptions: {
|
markdownOptions: {
|
||||||
remarkPlugins: ['remark-slug', ['remark-autolink-headings', { behavior: 'prepend' }]],
|
remarkPlugins: ['remark-slug', ['remark-autolink-headings', { behavior: 'prepend' }]],
|
||||||
rehypePlugins: ['rehype-slug', ['rehype-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
|
```js
|
||||||
export default {
|
export default {
|
||||||
name: '@matthewp/my-renderer',
|
name: '@matthewp/my-renderer',
|
||||||
server: './server.js',
|
server: './server.js',
|
||||||
client: './client.js',
|
client: './client.js',
|
||||||
hydrationPolyfills: ['./my-polyfill.js'],
|
hydrationPolyfills: ['./my-polyfill.js'],
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "astro",
|
"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.",
|
"description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "withastro",
|
"author": "withastro",
|
||||||
|
@ -54,11 +54,11 @@
|
||||||
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
||||||
"postbuild": "astro-scripts copy \"src/**/*.astro\"",
|
"postbuild": "astro-scripts copy \"src/**/*.astro\"",
|
||||||
"benchmark": "node test/benchmark/dev.bench.js && node test/benchmark/build.bench.js",
|
"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": "mocha --parallel --timeout 20000 --ignore **/lit-element.test.js && mocha --timeout 20000 **/lit-element.test.js",
|
||||||
"test:match": "mocha --timeout 15000 -g"
|
"test:match": "mocha --timeout 20000 -g"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/compiler": "^0.11.4",
|
"@astrojs/compiler": "^0.12.0-next.8",
|
||||||
"@astrojs/language-server": "^0.8.6",
|
"@astrojs/language-server": "^0.8.6",
|
||||||
"@astrojs/markdown-remark": "^0.6.4",
|
"@astrojs/markdown-remark": "^0.6.4",
|
||||||
"@astrojs/prism": "0.4.0",
|
"@astrojs/prism": "0.4.0",
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
"resolve": "^1.20.0",
|
"resolve": "^1.20.0",
|
||||||
"rollup": "^2.64.0",
|
"rollup": "^2.64.0",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"send": "^0.17.1",
|
"sirv": "^2.0.2",
|
||||||
"serialize-javascript": "^6.0.0",
|
"serialize-javascript": "^6.0.0",
|
||||||
"shiki": "^0.10.0",
|
"shiki": "^0.10.0",
|
||||||
"shorthash": "^0.0.2",
|
"shorthash": "^0.0.2",
|
||||||
|
|
|
@ -27,8 +27,10 @@ export interface CLIFlags {
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
port?: number;
|
port?: number;
|
||||||
config?: string;
|
config?: string;
|
||||||
|
/** @deprecated */
|
||||||
experimentalStaticBuild?: boolean;
|
experimentalStaticBuild?: boolean;
|
||||||
experimentalSsr?: boolean;
|
experimentalSsr?: boolean;
|
||||||
|
legacyBuild?: boolean;
|
||||||
drafts?: boolean;
|
drafts?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,12 +268,19 @@ export interface AstroUserConfig {
|
||||||
*/
|
*/
|
||||||
drafts?: boolean;
|
drafts?: boolean;
|
||||||
/**
|
/**
|
||||||
* Experimental: Enables "static build mode" for faster builds.
|
* Enables "legacy build mode" for compatibility with older Astro versions.
|
||||||
* Default: false
|
* Default: false
|
||||||
*/
|
*/
|
||||||
|
legacyBuild?: boolean;
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Experimental: Enables "static build mode" for faster builds.
|
||||||
|
* Default: true
|
||||||
|
*/
|
||||||
experimentalStaticBuild?: boolean;
|
experimentalStaticBuild?: boolean;
|
||||||
/**
|
/**
|
||||||
* Enable a build for SSR support.
|
* Enable a build for SSR support.
|
||||||
|
* Default: false
|
||||||
*/
|
*/
|
||||||
experimentalSsr?: boolean;
|
experimentalSsr?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -506,17 +515,6 @@ export type Params = Record<string, string | undefined>;
|
||||||
|
|
||||||
export type Props = Record<string, unknown>;
|
export type Props = Record<string, unknown>;
|
||||||
|
|
||||||
export interface RenderPageOptions {
|
|
||||||
request: {
|
|
||||||
params?: Params;
|
|
||||||
url: URL;
|
|
||||||
canonicalURL: URL;
|
|
||||||
};
|
|
||||||
children: any[];
|
|
||||||
props: Props;
|
|
||||||
css?: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
type Body = string;
|
type Body = string;
|
||||||
|
|
||||||
export interface EndpointOutput<Output extends Body = Body> {
|
export interface EndpointOutput<Output extends Body = Body> {
|
||||||
|
@ -634,7 +632,7 @@ export interface SSRElement {
|
||||||
export interface SSRMetadata {
|
export interface SSRMetadata {
|
||||||
renderers: Renderer[];
|
renderers: Renderer[];
|
||||||
pathname: string;
|
pathname: string;
|
||||||
experimentalStaticBuild: boolean;
|
legacyBuild: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SSRResult {
|
export interface SSRResult {
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class App {
|
||||||
const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site);
|
const scripts = createModuleScriptElementWithSrcSet(info.scripts, manifest.site);
|
||||||
|
|
||||||
return render({
|
return render({
|
||||||
experimentalStaticBuild: true,
|
legacyBuild: false,
|
||||||
links,
|
links,
|
||||||
logging: defaultLogOptions,
|
logging: defaultLogOptions,
|
||||||
markdownRender: manifest.markdown.render,
|
markdownRender: manifest.markdown.render,
|
||||||
|
|
|
@ -110,7 +110,7 @@ class AstroBuilder {
|
||||||
timer.buildStart = performance.now();
|
timer.buildStart = performance.now();
|
||||||
|
|
||||||
// Use the new faster static based build.
|
// Use the new faster static based build.
|
||||||
if (this.config.buildOptions.experimentalStaticBuild) {
|
if (!this.config.buildOptions.legacyBuild) {
|
||||||
await staticBuild({
|
await staticBuild({
|
||||||
allPages,
|
allPages,
|
||||||
astroConfig: this.config,
|
astroConfig: this.config,
|
||||||
|
|
|
@ -38,9 +38,10 @@ export interface StaticBuildOptions {
|
||||||
|
|
||||||
const MAX_CONCURRENT_RENDERS = 10;
|
const MAX_CONCURRENT_RENDERS = 10;
|
||||||
|
|
||||||
|
const STATUS_CODE_PAGES = new Set(['/404', '/500']);
|
||||||
|
|
||||||
function addPageName(pathname: string, opts: StaticBuildOptions): void {
|
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(/\/?$/, '/').replace(/^\//, ''));
|
||||||
opts.pageNames.push(pathname.replace(/\/?$/, pathrepl).replace(/^\//, ''));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gives back a facadeId that is relative to the root.
|
// Gives back a facadeId that is relative to the root.
|
||||||
|
@ -131,6 +132,8 @@ export async function staticBuild(opts: StaticBuildOptions) {
|
||||||
const topLevelImports = new Set([
|
const topLevelImports = new Set([
|
||||||
// Any component that gets hydrated
|
// Any component that gets hydrated
|
||||||
...metadata.hydratedComponentPaths(),
|
...metadata.hydratedComponentPaths(),
|
||||||
|
// Client-only components
|
||||||
|
...metadata.clientOnlyComponentPaths(),
|
||||||
// Any hydration directive like astro/client/idle.js
|
// Any hydration directive like astro/client/idle.js
|
||||||
...metadata.hydrationDirectiveSpecifiers(),
|
...metadata.hydrationDirectiveSpecifiers(),
|
||||||
// The client path for each renderer
|
// The client path for each renderer
|
||||||
|
@ -182,6 +185,7 @@ async function ssrBuild(opts: StaticBuildOptions, internals: BuildInternals, inp
|
||||||
logLevel: 'error',
|
logLevel: 'error',
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
build: {
|
build: {
|
||||||
|
...viteConfig.build,
|
||||||
emptyOutDir: false,
|
emptyOutDir: false,
|
||||||
manifest: ssr,
|
manifest: ssr,
|
||||||
minify: false,
|
minify: false,
|
||||||
|
@ -360,12 +364,12 @@ async function generatePath(pathname: string, opts: StaticBuildOptions, gopts: G
|
||||||
debug('build', `Generating: ${pathname}`);
|
debug('build', `Generating: ${pathname}`);
|
||||||
|
|
||||||
const site = astroConfig.buildOptions.site;
|
const site = astroConfig.buildOptions.site;
|
||||||
const links = createLinkStylesheetElementSet(linkIds, site);
|
const links = createLinkStylesheetElementSet(linkIds.reverse(), site);
|
||||||
const scripts = createModuleScriptElementWithSrcSet(hoistedId ? [hoistedId] : [], site);
|
const scripts = createModuleScriptElementWithSrcSet(hoistedId ? [hoistedId] : [], site);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const html = await render({
|
const html = await render({
|
||||||
experimentalStaticBuild: true,
|
legacyBuild: false,
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdownRender: astroConfig.markdownOptions.render,
|
markdownRender: astroConfig.markdownOptions.render,
|
||||||
|
@ -454,8 +458,7 @@ async function generateManifest(result: RollupOutput, opts: StaticBuildOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOutRoot(astroConfig: AstroConfig): URL {
|
function getOutRoot(astroConfig: AstroConfig): URL {
|
||||||
const rootPathname = appendForwardSlash(astroConfig.buildOptions.site ? new URL(astroConfig.buildOptions.site).pathname : '/');
|
return new URL('./', astroConfig.dist);
|
||||||
return new URL('.' + rootPathname, astroConfig.dist);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getServerRoot(astroConfig: AstroConfig): URL {
|
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);
|
return new URL('.' + appendForwardSlash(npath.dirname(pathname)), outRoot);
|
||||||
case 'page':
|
case 'page':
|
||||||
switch (astroConfig.buildOptions.pageUrlFormat) {
|
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);
|
return new URL('.' + appendForwardSlash(pathname), outRoot);
|
||||||
case 'file':
|
}
|
||||||
|
case 'file': {
|
||||||
return new URL('.' + appendForwardSlash(npath.dirname(pathname)), outRoot);
|
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);
|
return new URL(npath.basename(pathname), outFolder);
|
||||||
case 'page':
|
case 'page':
|
||||||
switch (astroConfig.buildOptions.pageUrlFormat) {
|
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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,11 +26,6 @@ export const AstroConfigSchema = z.object({
|
||||||
.optional()
|
.optional()
|
||||||
.default('./src/pages')
|
.default('./src/pages')
|
||||||
.transform((val) => new URL(val)),
|
.transform((val) => new URL(val)),
|
||||||
layouts: z
|
|
||||||
.string()
|
|
||||||
.optional()
|
|
||||||
.default('./src/layouts')
|
|
||||||
.transform((val) => new URL(val)),
|
|
||||||
public: z
|
public: z
|
||||||
.string()
|
.string()
|
||||||
.optional()
|
.optional()
|
||||||
|
@ -60,7 +55,8 @@ export const AstroConfigSchema = z.object({
|
||||||
.union([z.literal('file'), z.literal('directory')])
|
.union([z.literal('file'), z.literal('directory')])
|
||||||
.optional()
|
.optional()
|
||||||
.default('directory'),
|
.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),
|
experimentalSsr: z.boolean().optional().default(false),
|
||||||
drafts: z.boolean().optional().default(false),
|
drafts: z.boolean().optional().default(false),
|
||||||
})
|
})
|
||||||
|
@ -98,10 +94,6 @@ export async function validateConfig(userConfig: any, root: string): Promise<Ast
|
||||||
.string()
|
.string()
|
||||||
.default('./src/pages')
|
.default('./src/pages')
|
||||||
.transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)),
|
.transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)),
|
||||||
layouts: z
|
|
||||||
.string()
|
|
||||||
.default('./src/layouts')
|
|
||||||
.transform((val) => new URL(addTrailingSlash(val), fileProtocolRoot)),
|
|
||||||
public: z
|
public: z
|
||||||
.string()
|
.string()
|
||||||
.default('./public')
|
.default('./public')
|
||||||
|
@ -121,6 +113,11 @@ function addTrailingSlash(str: string): string {
|
||||||
|
|
||||||
/** Convert the generic "yargs" flag object into our own, custom TypeScript object. */
|
/** Convert the generic "yargs" flag object into our own, custom TypeScript object. */
|
||||||
function resolveFlags(flags: Partial<Flags>): CLIFlags {
|
function resolveFlags(flags: Partial<Flags>): 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 {
|
return {
|
||||||
projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot : undefined,
|
projectRoot: typeof flags.projectRoot === 'string' ? flags.projectRoot : undefined,
|
||||||
site: typeof flags.site === 'string' ? flags.site : undefined,
|
site: typeof flags.site === 'string' ? flags.site : undefined,
|
||||||
|
@ -128,7 +125,8 @@ function resolveFlags(flags: Partial<Flags>): CLIFlags {
|
||||||
port: typeof flags.port === 'number' ? flags.port : undefined,
|
port: typeof flags.port === 'number' ? flags.port : undefined,
|
||||||
config: typeof flags.config === 'string' ? flags.config : undefined,
|
config: typeof flags.config === 'string' ? flags.config : undefined,
|
||||||
hostname: typeof flags.hostname === 'string' ? flags.hostname : 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,
|
experimentalSsr: typeof flags.experimentalSsr === 'boolean' ? flags.experimentalSsr : false,
|
||||||
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : false,
|
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : false,
|
||||||
};
|
};
|
||||||
|
@ -147,6 +145,7 @@ function mergeCLIFlags(astroConfig: AstroUserConfig, flags: CLIFlags) {
|
||||||
astroConfig.buildOptions.experimentalSsr = flags.experimentalSsr;
|
astroConfig.buildOptions.experimentalSsr = flags.experimentalSsr;
|
||||||
if (flags.experimentalSsr) {
|
if (flags.experimentalSsr) {
|
||||||
astroConfig.buildOptions.experimentalStaticBuild = true;
|
astroConfig.buildOptions.experimentalStaticBuild = true;
|
||||||
|
astroConfig.buildOptions.legacyBuild = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof flags.drafts === 'boolean') astroConfig.buildOptions.drafts = flags.drafts;
|
if (typeof flags.drafts === 'boolean') astroConfig.buildOptions.drafts = flags.drafts;
|
||||||
|
|
|
@ -2,17 +2,15 @@ import type { AstroConfig } from '../../@types/astro';
|
||||||
import type { LogOptions } from '../logger';
|
import type { LogOptions } from '../logger';
|
||||||
import type { Stats } from 'fs';
|
import type { Stats } from 'fs';
|
||||||
import type { AddressInfo } from 'net';
|
import type { AddressInfo } from 'net';
|
||||||
|
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
|
import sirv from 'sirv';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import send from 'send';
|
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import fs from 'fs';
|
|
||||||
import * as msg from '../messages.js';
|
import * as msg from '../messages.js';
|
||||||
import { error, info } from '../logger.js';
|
import { error, info } from '../logger.js';
|
||||||
import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js';
|
|
||||||
import { appendForwardSlash, trimSlashes } from '../path.js';
|
import { appendForwardSlash, trimSlashes } from '../path.js';
|
||||||
import { getLocalAddress } from '../dev/util.js';
|
import { getLocalAddress } from '../dev/util.js';
|
||||||
|
import { subpathNotUsedTemplate, notFoundTemplate } from '../../template/4xx.js';
|
||||||
|
|
||||||
interface PreviewOptions {
|
interface PreviewOptions {
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
|
@ -25,28 +23,19 @@ export interface PreviewServer {
|
||||||
stop(): Promise<void>;
|
stop(): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const HAS_FILE_EXTENSION_REGEXP = /^.*\.[^\\]+$/;
|
||||||
|
|
||||||
/** The primary dev action */
|
/** The primary dev action */
|
||||||
export default async function preview(config: AstroConfig, { logging }: PreviewOptions): Promise<PreviewServer> {
|
export default async function preview(config: AstroConfig, { logging }: PreviewOptions): Promise<PreviewServer> {
|
||||||
const startServerTime = performance.now();
|
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 defaultOrigin = 'http://localhost';
|
||||||
|
const trailingSlash = config.devOptions.trailingSlash
|
||||||
const sendOptions = {
|
|
||||||
extensions: pageUrlFormat === 'file' ? ['html'] : false,
|
|
||||||
index: false,
|
|
||||||
root: fileURLToPath(config.dist),
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Base request URL. */
|
/** Base request URL. */
|
||||||
let baseURL = new URL(config.buildOptions.site || '/', defaultOrigin);
|
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.
|
// Create the preview server, send static files out of the `dist/` directory.
|
||||||
const server = http.createServer((req, res) => {
|
const server = http.createServer((req, res) => {
|
||||||
const requestURL = new URL(req.url as string, defaultOrigin);
|
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 isRoot = pathname === '/';
|
||||||
const hasTrailingSlash = isRoot || pathname.endsWith('/');
|
const hasTrailingSlash = isRoot || pathname.endsWith('/');
|
||||||
|
|
||||||
let tryTrailingSlash = true;
|
function sendError(message: string) {
|
||||||
let tryHtmlExtension = true;
|
|
||||||
|
|
||||||
let url: URL;
|
|
||||||
|
|
||||||
const onErr = (message: string) => {
|
|
||||||
res.statusCode = 404;
|
res.statusCode = 404;
|
||||||
res.end(notFoundTemplate(pathname, message));
|
res.end(notFoundTemplate(pathname, message));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onStat = (err: NodeJS.ErrnoException | null, stat: Stats) => {
|
switch (true) {
|
||||||
switch (true) {
|
case hasTrailingSlash && trailingSlash == 'never' && !isRoot:
|
||||||
// retry nonexistent paths without an html extension
|
sendError('Not Found (devOptions.trailingSlash is set to "never")');
|
||||||
case err && tryHtmlExtension && hasTrailingSlash && !blockTrailingSlash:
|
return;
|
||||||
case err && tryHtmlExtension && !hasTrailingSlash && !forceTrailingSlash && !pathname.endsWith('.html'):
|
case !hasTrailingSlash && trailingSlash == 'always' && !isRoot && !HAS_FILE_EXTENSION_REGEXP.test(pathname):
|
||||||
tryHtmlExtension = false;
|
sendError('Not Found (devOptions.trailingSlash is set to "always")');
|
||||||
return fs.stat((url = new URL(url.pathname + '.html', url)), onStat);
|
return;
|
||||||
|
default: {
|
||||||
// 404 on nonexistent paths (that are yet handled)
|
// HACK: rewrite req.url so that sirv finds the file
|
||||||
case err !== null:
|
req.url = '/' + req.url?.replace(baseURL.pathname, '')
|
||||||
return onErr('Path not found');
|
staticFileServer(req, res, () => sendError('Not Found'));
|
||||||
|
return;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
fs.stat((url = new URL(trimSlashes(pathname), config.dist)), onStat);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let { hostname, port } = config.devOptions;
|
let { hostname, port } = config.devOptions;
|
||||||
|
@ -165,7 +124,9 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO
|
||||||
port,
|
port,
|
||||||
server: httpServer!,
|
server: httpServer!,
|
||||||
stop: async () => {
|
stop: async () => {
|
||||||
httpServer.close();
|
await new Promise((resolve, reject) => {
|
||||||
|
httpServer.close((err) => err ? reject(err) : resolve(undefined));
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ComponentInstance, EndpointHandler, MarkdownRenderOptions, Params, Props, Renderer, RouteData, SSRElement } from '../../@types/astro';
|
import type { ComponentInstance, EndpointHandler, MarkdownRenderOptions, Params, Props, Renderer, RouteData, SSRElement } from '../../@types/astro';
|
||||||
import type { LogOptions } from '../logger.js';
|
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 { getParams } from '../routing/index.js';
|
||||||
import { createResult } from './result.js';
|
import { createResult } from './result.js';
|
||||||
import { findPathItemByKey, RouteCache, callGetStaticPaths } from './route-cache.js';
|
import { findPathItemByKey, RouteCache, callGetStaticPaths } from './route-cache.js';
|
||||||
|
@ -50,7 +50,7 @@ async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise<[Param
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RenderOptions {
|
interface RenderOptions {
|
||||||
experimentalStaticBuild: boolean;
|
legacyBuild: boolean;
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
links: Set<SSRElement>;
|
links: Set<SSRElement>;
|
||||||
markdownRender: MarkdownRenderOptions;
|
markdownRender: MarkdownRenderOptions;
|
||||||
|
@ -66,7 +66,7 @@ interface RenderOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function render(opts: RenderOptions): Promise<string> {
|
export async function render(opts: RenderOptions): Promise<string> {
|
||||||
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({
|
const [params, pageProps] = await getParamsAndProps({
|
||||||
logging,
|
logging,
|
||||||
|
@ -87,7 +87,7 @@ export async function render(opts: RenderOptions): Promise<string> {
|
||||||
if (!Component.isAstroComponentFactory) throw new Error(`Unable to SSR non-Astro component (${route?.component})`);
|
if (!Component.isAstroComponentFactory) throw new Error(`Unable to SSR non-Astro component (${route?.component})`);
|
||||||
|
|
||||||
const result = createResult({
|
const result = createResult({
|
||||||
experimentalStaticBuild,
|
legacyBuild,
|
||||||
links,
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdownRender,
|
markdownRender,
|
||||||
|
@ -100,10 +100,17 @@ export async function render(opts: RenderOptions): Promise<string> {
|
||||||
scripts,
|
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("<!--astro:head:injected-->") == -1) {
|
||||||
|
html = await renderHead(result) + html;
|
||||||
|
}
|
||||||
|
// cleanup internal state flags
|
||||||
|
html = html.replace("<!--astro:head:injected-->", '');
|
||||||
|
|
||||||
// inject <!doctype html> if missing (TODO: is a more robust check needed for comments, etc.?)
|
// inject <!doctype html> if missing (TODO: is a more robust check needed for comments, etc.?)
|
||||||
if (experimentalStaticBuild && !/<!doctype html/i.test(html)) {
|
if (!legacyBuild && !/<!doctype html/i.test(html)) {
|
||||||
html = '<!DOCTYPE html>\n' + html;
|
html = '<!DOCTYPE html>\n' + html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import type * as vite from 'vite';
|
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 { LogOptions } from '../../logger.js';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { getStylesForURL } from './css.js';
|
import { getStylesForURL } from './css.js';
|
||||||
|
@ -48,14 +48,15 @@ export async function preload({ astroConfig, filePath, viteServer }: SSROptions)
|
||||||
/** use Vite to SSR */
|
/** use Vite to SSR */
|
||||||
export async function render(renderers: Renderer[], mod: ComponentInstance, ssrOpts: SSROptions): Promise<string> {
|
export async function render(renderers: Renderer[], mod: ComponentInstance, ssrOpts: SSROptions): Promise<string> {
|
||||||
const { astroConfig, filePath, logging, mode, origin, pathname, route, routeCache, viteServer } = ssrOpts;
|
const { astroConfig, filePath, logging, mode, origin, pathname, route, routeCache, viteServer } = ssrOpts;
|
||||||
|
const legacy = astroConfig.buildOptions.legacyBuild;
|
||||||
|
|
||||||
// Add hoisted script tags
|
// Add hoisted script tags
|
||||||
const scripts = createModuleScriptElementWithSrcSet(
|
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
|
// Inject HMR scripts
|
||||||
if (mod.hasOwnProperty('$$metadata') && mode === 'development' && astroConfig.buildOptions.experimentalStaticBuild) {
|
if (mod.hasOwnProperty('$$metadata') && mode === 'development' && !legacy) {
|
||||||
scripts.add({
|
scripts.add({
|
||||||
props: { type: 'module', src: '/@vite/client' },
|
props: { type: 'module', src: '/@vite/client' },
|
||||||
children: '',
|
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<SSRElement>();
|
||||||
|
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({
|
let content = await coreRender({
|
||||||
experimentalStaticBuild: astroConfig.buildOptions.experimentalStaticBuild,
|
legacyBuild: astroConfig.buildOptions.legacyBuild,
|
||||||
links: new Set(),
|
links,
|
||||||
logging,
|
logging,
|
||||||
markdownRender: astroConfig.markdownOptions.render,
|
markdownRender: astroConfig.markdownOptions.render,
|
||||||
mod,
|
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
|
// The legacy build needs these to remain unresolved so that vite HTML
|
||||||
// Can do the resolution. Without this condition the build output will be
|
// 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.
|
// 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);
|
const [, resolvedPath] = await viteServer.moduleGraph.resolveUrl(s);
|
||||||
return resolvedPath;
|
return resolvedPath;
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,7 +124,7 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO
|
||||||
const tags: vite.HtmlTagDescriptor[] = [];
|
const tags: vite.HtmlTagDescriptor[] = [];
|
||||||
|
|
||||||
// dev only: inject Astro HMR client
|
// dev only: inject Astro HMR client
|
||||||
if (mode === 'development' && !astroConfig.buildOptions.experimentalStaticBuild) {
|
if (mode === 'development' && legacy) {
|
||||||
tags.push({
|
tags.push({
|
||||||
tag: 'script',
|
tag: 'script',
|
||||||
attrs: { type: 'module' },
|
attrs: { type: 'module' },
|
||||||
|
@ -113,31 +136,34 @@ export async function render(renderers: Renderer[], mod: ComponentInstance, ssrO
|
||||||
}
|
}
|
||||||
|
|
||||||
// inject CSS
|
// inject CSS
|
||||||
[...getStylesForURL(filePath, viteServer)].forEach((href) => {
|
if(legacy) {
|
||||||
if (mode === 'development' && svelteStylesRE.test(href)) {
|
[...getStylesForURL(filePath, viteServer)].forEach((href) => {
|
||||||
tags.push({
|
if (mode === 'development' && svelteStylesRE.test(href)) {
|
||||||
tag: 'script',
|
tags.push({
|
||||||
attrs: { type: 'module', src: href },
|
tag: 'script',
|
||||||
injectTo: 'head',
|
attrs: { type: 'module', src: href },
|
||||||
});
|
injectTo: 'head',
|
||||||
} else {
|
});
|
||||||
tags.push({
|
} else {
|
||||||
tag: 'link',
|
tags.push({
|
||||||
attrs: {
|
tag: 'link',
|
||||||
rel: 'stylesheet',
|
attrs: {
|
||||||
href,
|
rel: 'stylesheet',
|
||||||
'data-astro-injected': true,
|
href,
|
||||||
},
|
'data-astro-injected': true,
|
||||||
injectTo: 'head',
|
},
|
||||||
});
|
injectTo: 'head',
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// add injected tags
|
// add injected tags
|
||||||
content = injectTags(content, tags);
|
content = injectTags(content, tags);
|
||||||
|
|
||||||
// run transformIndexHtml() in dev to run Vite dev transformations
|
// 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, '/');
|
const relativeURL = filePath.href.replace(astroConfig.projectRoot.href, '/');
|
||||||
content = await viteServer.transformIndexHtml(relativeURL, content, pathname);
|
content = await viteServer.transformIndexHtml(relativeURL, content, pathname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ import { renderSlot } from '../../runtime/server/index.js';
|
||||||
import { warn, LogOptions } from '../logger.js';
|
import { warn, LogOptions } from '../logger.js';
|
||||||
|
|
||||||
export interface CreateResultArgs {
|
export interface CreateResultArgs {
|
||||||
experimentalStaticBuild: boolean;
|
legacyBuild: boolean;
|
||||||
logging: LogOptions;
|
logging: LogOptions;
|
||||||
origin: string;
|
origin: string;
|
||||||
markdownRender: MarkdownRenderOptions;
|
markdownRender: MarkdownRenderOptions;
|
||||||
|
@ -22,7 +22,7 @@ export interface CreateResultArgs {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createResult(args: CreateResultArgs): SSRResult {
|
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.
|
// 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
|
// 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,
|
url,
|
||||||
},
|
},
|
||||||
resolve(path: string) {
|
resolve(path: string) {
|
||||||
if (experimentalStaticBuild) {
|
if (!legacyBuild) {
|
||||||
let extra = `This can be replaced with a dynamic import like so: await import("${path}")`;
|
let extra = `This can be replaced with a dynamic import like so: await import("${path}")`;
|
||||||
if (isCSSRequest(path)) {
|
if (isCSSRequest(path)) {
|
||||||
extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this:
|
extra = `It looks like you are resolving styles. If you are adding a link tag, replace with this:
|
||||||
|
@ -116,7 +116,7 @@ ${extra}`
|
||||||
_metadata: {
|
_metadata: {
|
||||||
renderers,
|
renderers,
|
||||||
pathname,
|
pathname,
|
||||||
experimentalStaticBuild,
|
legacyBuild
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/;
|
||||||
/** Construct sitemap.xml given a set of URLs */
|
/** Construct sitemap.xml given a set of URLs */
|
||||||
export function generateSitemap(pages: string[]): string {
|
export function generateSitemap(pages: string[]): string {
|
||||||
// TODO: find way to respect <link rel="canonical"> URLs here
|
// TODO: find way to respect <link rel="canonical"> URLs here
|
||||||
|
|
||||||
// TODO: find way to exclude pages from sitemap
|
// TODO: find way to exclude pages from sitemap
|
||||||
|
|
||||||
// copy just in case original copy is needed
|
// copy just in case original copy is needed
|
||||||
|
|
|
@ -216,7 +216,7 @@ export function createRouteManifest({ config, cwd }: { config: AstroConfig; cwd?
|
||||||
basename,
|
basename,
|
||||||
ext,
|
ext,
|
||||||
parts,
|
parts,
|
||||||
file: slash(file),
|
file: file.replace(/\\/g, '/'),
|
||||||
isDir,
|
isDir,
|
||||||
isIndex,
|
isIndex,
|
||||||
isPage,
|
isPage,
|
||||||
|
|
|
@ -71,7 +71,7 @@ export class AstroComponent {
|
||||||
const html = htmlParts[i];
|
const html = htmlParts[i];
|
||||||
const expression = expressions[i];
|
const expression = expressions[i];
|
||||||
|
|
||||||
yield _render(unescapeHTML(html));
|
yield unescapeHTML(html);
|
||||||
yield _render(expression);
|
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']);
|
const STATIC_DIRECTIVES = new Set(['set:html', 'set:text']);
|
||||||
|
|
||||||
// A helper used to turn expressions into attribute key/value
|
// 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) {
|
if (value == null) {
|
||||||
return '';
|
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))) {
|
if (value === true && (key.startsWith('data-') || htmlBooleanAttributes.test(key))) {
|
||||||
return unescapeHTML(` ${key}`);
|
return unescapeHTML(` ${key}`);
|
||||||
} else {
|
} else {
|
||||||
return unescapeHTML(` ${key}="${toAttributeString(value)}"`);
|
return unescapeHTML(` ${key}="${toAttributeString(value, shouldEscape)}"`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds support for `<Component {...value} />
|
// Adds support for `<Component {...value} />
|
||||||
export function spreadAttributes(values: Record<any, any>) {
|
export function spreadAttributes(values: Record<any, any>, shouldEscape = true) {
|
||||||
let output = '';
|
let output = '';
|
||||||
for (const [key, value] of Object.entries(values)) {
|
for (const [key, value] of Object.entries(values)) {
|
||||||
output += addAttribute(value, key);
|
output += addAttribute(value, key, shouldEscape);
|
||||||
}
|
}
|
||||||
return unescapeHTML(output);
|
return unescapeHTML(output);
|
||||||
}
|
}
|
||||||
|
@ -403,20 +405,6 @@ export function defineScriptVars(vars: Record<any, any>) {
|
||||||
return output;
|
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.
|
// Renders an endpoint request to completion, returning the body.
|
||||||
export async function renderEndpoint(mod: EndpointHandler, params: any) {
|
export async function renderEndpoint(mod: EndpointHandler, params: any) {
|
||||||
const method = 'get';
|
const method = 'get';
|
||||||
|
@ -431,15 +419,34 @@ export async function renderEndpoint(mod: EndpointHandler, params: any) {
|
||||||
return body;
|
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);
|
||||||
|
|
||||||
|
// <!--astro:head--> injected by compiler
|
||||||
|
// Must be handled at the end of the rendering process
|
||||||
|
if (template.indexOf('<!--astro:head-->') > -1) {
|
||||||
|
template = template.replace('<!--astro:head-->', 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
|
// Renders a page to completion by first calling the factory callback, waiting for its result, and then appending
|
||||||
// styles and scripts into the head.
|
// styles and scripts into the head.
|
||||||
export async function renderPage(result: SSRResult, Component: AstroComponentFactory, props: any, children: any) {
|
export async function renderHead(result: SSRResult) {
|
||||||
const template = await renderToString(result, Component, props, children);
|
|
||||||
const styles = Array.from(result.styles)
|
const styles = Array.from(result.styles)
|
||||||
.filter(uniqueElements)
|
.filter(uniqueElements)
|
||||||
.map((style) => {
|
.map((style) => {
|
||||||
const styleChildren = result._metadata.experimentalStaticBuild ? '' : style.children;
|
const styleChildren = !result._metadata.legacyBuild ? '' : style.children;
|
||||||
|
|
||||||
return renderElement('style', {
|
return renderElement('style', {
|
||||||
children: styleChildren,
|
children: styleChildren,
|
||||||
props: { ...style.props, 'astro-style': true },
|
props: { ...style.props, 'astro-style': true },
|
||||||
|
@ -460,17 +467,10 @@ export async function renderPage(result: SSRResult, Component: AstroComponentFac
|
||||||
if (needsHydrationStyles) {
|
if (needsHydrationStyles) {
|
||||||
styles.push(renderElement('style', { props: { 'astro-style': true }, children: 'astro-root, astro-fragment { display: contents; }' }));
|
styles.push(renderElement('style', { props: { 'astro-style': true }, children: 'astro-root, astro-fragment { display: contents; }' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const links = Array.from(result.links)
|
const links = Array.from(result.links)
|
||||||
.filter(uniqueElements)
|
.filter(uniqueElements)
|
||||||
.map((link) => renderElement('link', link));
|
.map((link) => renderElement('link', link, false));
|
||||||
|
return unescapeHTML(links.join('\n') + styles.join('\n') + scripts.join('\n') + '\n' + '<!--astro:head:injected-->');
|
||||||
// inject styles & scripts at end of <head>
|
|
||||||
let headPos = template.indexOf('</head>');
|
|
||||||
if (headPos === -1) {
|
|
||||||
return links.join('\n') + styles.join('\n') + scripts.join('\n') + template; // if no </head>, prepend styles & scripts
|
|
||||||
}
|
|
||||||
return template.substring(0, headPos) + links.join('\n') + styles.join('\n') + scripts.join('\n') + template.substring(headPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renderAstroComponent(component: InstanceType<typeof AstroComponent>) {
|
export async function renderAstroComponent(component: InstanceType<typeof AstroComponent>) {
|
||||||
|
@ -513,7 +513,7 @@ function getHTMLElementName(constructor: typeof HTMLElement) {
|
||||||
return assignedName;
|
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`
|
// Do not print `hoist`, `lang`, `global`
|
||||||
const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props;
|
const { lang: _, 'data-astro-id': astroId, 'define:vars': defineVars, ...props } = _props;
|
||||||
if (defineVars) {
|
if (defineVars) {
|
||||||
|
@ -530,5 +530,5 @@ function renderElement(name: string, { props: _props, children = '' }: SSRElemen
|
||||||
children = defineScriptVars(defineVars) + '\n' + children;
|
children = defineScriptVars(defineVars) + '\n' + children;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return `<${name}${spreadAttributes(props)}>${children}</${name}>`;
|
return `<${name}${spreadAttributes(props, shouldEscape)}>${children}</${name}>`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ interface ComponentMetadata {
|
||||||
interface CreateMetadataOptions {
|
interface CreateMetadataOptions {
|
||||||
modules: ModuleInfo[];
|
modules: ModuleInfo[];
|
||||||
hydratedComponents: any[];
|
hydratedComponents: any[];
|
||||||
|
clientOnlyComponents: any[];
|
||||||
hydrationDirectives: Set<string>;
|
hydrationDirectives: Set<string>;
|
||||||
hoisted: any[];
|
hoisted: any[];
|
||||||
}
|
}
|
||||||
|
@ -22,6 +23,7 @@ export class Metadata {
|
||||||
public modules: ModuleInfo[];
|
public modules: ModuleInfo[];
|
||||||
public hoisted: any[];
|
public hoisted: any[];
|
||||||
public hydratedComponents: any[];
|
public hydratedComponents: any[];
|
||||||
|
public clientOnlyComponents: any[];
|
||||||
public hydrationDirectives: Set<string>;
|
public hydrationDirectives: Set<string>;
|
||||||
|
|
||||||
private metadataCache: Map<any, ComponentMetadata | null>;
|
private metadataCache: Map<any, ComponentMetadata | null>;
|
||||||
|
@ -30,6 +32,7 @@ export class Metadata {
|
||||||
this.modules = opts.modules;
|
this.modules = opts.modules;
|
||||||
this.hoisted = opts.hoisted;
|
this.hoisted = opts.hoisted;
|
||||||
this.hydratedComponents = opts.hydratedComponents;
|
this.hydratedComponents = opts.hydratedComponents;
|
||||||
|
this.clientOnlyComponents = opts.clientOnlyComponents;
|
||||||
this.hydrationDirectives = opts.hydrationDirectives;
|
this.hydrationDirectives = opts.hydrationDirectives;
|
||||||
this.mockURL = new URL(filePathname, 'http://example.com');
|
this.mockURL = new URL(filePathname, 'http://example.com');
|
||||||
this.metadataCache = new Map<any, ComponentMetadata | null>();
|
this.metadataCache = new Map<any, ComponentMetadata | null>();
|
||||||
|
@ -66,6 +69,19 @@ export class Metadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*clientOnlyComponentPaths() {
|
||||||
|
const found = new Set<string>();
|
||||||
|
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.
|
* Gets all of the hydration specifiers used within this component.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,11 +33,8 @@ function safelyReplaceImportPlaceholder(code: string) {
|
||||||
const configCache = new WeakMap<AstroConfig, CompilationCache>();
|
const configCache = new WeakMap<AstroConfig, CompilationCache>();
|
||||||
|
|
||||||
async function compile(config: AstroConfig, filename: string, source: string, viteTransform: TransformHook, opts: { ssr: boolean }): Promise<CompileResult> {
|
async function compile(config: AstroConfig, filename: string, source: string, viteTransform: TransformHook, opts: { ssr: boolean }): Promise<CompileResult> {
|
||||||
// pages and layouts should be transformed as full documents (implicit <head> <body> etc)
|
|
||||||
// everything else is treated as a fragment
|
|
||||||
const filenameURL = new URL(`file://${filename}`);
|
const filenameURL = new URL(`file://${filename}`);
|
||||||
const normalizedID = fileURLToPath(filenameURL);
|
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);
|
const pathname = filenameURL.pathname.substr(config.projectRoot.pathname.length - 1);
|
||||||
|
|
||||||
let rawCSSDeps = new Set<string>();
|
let rawCSSDeps = new Set<string>();
|
||||||
|
@ -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
|
// use `sourcemap: "both"` so that sourcemap is included in the code
|
||||||
// result passed to esbuild, but also available in the catch handler.
|
// result passed to esbuild, but also available in the catch handler.
|
||||||
const transformResult = await transform(source, {
|
const transformResult = await transform(source, {
|
||||||
as: isPage ? 'document' : 'fragment',
|
|
||||||
pathname,
|
pathname,
|
||||||
projectRoot: config.projectRoot.toString(),
|
projectRoot: config.projectRoot.toString(),
|
||||||
site: config.buildOptions.site,
|
site: config.buildOptions.site,
|
||||||
sourcefile: filename,
|
sourcefile: filename,
|
||||||
sourcemap: 'both',
|
sourcemap: 'both',
|
||||||
internalURL: `/@fs${new URL('../runtime/server/index.js', import.meta.url).pathname}`,
|
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
|
// TODO add experimental flag here
|
||||||
preprocessStyle: async (value: string, attrs: Record<string, string>) => {
|
preprocessStyle: async (value: string, attrs: Record<string, string>) => {
|
||||||
const lang = `.${attrs?.lang || 'css'}`.toLowerCase();
|
const lang = `.${attrs?.lang || 'css'}`.toLowerCase();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// In the static build, grab any @import as CSS dependencies for HMR.
|
// In the static build, grab any @import as CSS dependencies for HMR.
|
||||||
if (config.buildOptions.experimentalStaticBuild) {
|
if (!config.buildOptions.legacyBuild) {
|
||||||
value = value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => {
|
value.replace(/(?:@import)\s(?:url\()?\s?["\'](.*?)["\']\s?\)?(?:[^;]*);?/gi, (match, spec) => {
|
||||||
rawCSSDeps.add(spec);
|
rawCSSDeps.add(spec);
|
||||||
// If the language is CSS: prevent `@import` inlining to prevent scoping of imports.
|
// 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.
|
// Otherwise: Sass, etc. need to see imports for variables, so leave in for their compiler to handle.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import type * as vite from 'vite';
|
import type * as vite from 'vite';
|
||||||
import type { AstroConfig } from '../@types/astro';
|
import type { AstroConfig } from '../@types/astro';
|
||||||
|
import type { TransformPluginContext } from 'rollup';
|
||||||
import MagicString from 'magic-string';
|
import MagicString from 'magic-string';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import { loadEnv } from 'vite';
|
import { loadEnv } from 'vite';
|
||||||
|
@ -30,7 +31,7 @@ function getPrivateEnv(viteConfig: vite.ResolvedConfig, astroConfig: AstroConfig
|
||||||
if (privateKeys.length === 0) {
|
if (privateKeys.length === 0) {
|
||||||
return null;
|
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<string, any>) {
|
function referencesPrivateKey(source: string, privateEnv: Record<string, any>) {
|
||||||
|
@ -43,39 +44,56 @@ function referencesPrivateKey(source: string, privateEnv: Record<string, any>) {
|
||||||
export default function envVitePlugin({ config: astroConfig }: EnvPluginOptions): vite.PluginOption {
|
export default function envVitePlugin({ config: astroConfig }: EnvPluginOptions): vite.PluginOption {
|
||||||
let privateEnv: Record<string, any> | null;
|
let privateEnv: Record<string, any> | null;
|
||||||
let config: vite.ResolvedConfig;
|
let config: vite.ResolvedConfig;
|
||||||
|
let replacements: Record<string, string>;
|
||||||
|
let pattern: RegExp | undefined;
|
||||||
return {
|
return {
|
||||||
name: 'astro:vite-plugin-env',
|
name: 'astro:vite-plugin-env',
|
||||||
enforce: 'pre',
|
enforce: 'pre',
|
||||||
|
|
||||||
configResolved(resolvedConfig) {
|
configResolved(resolvedConfig) {
|
||||||
config = resolvedConfig;
|
config = resolvedConfig;
|
||||||
if (config.envPrefix) {
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async transform(source, id, options) {
|
async transform(source, id, options) {
|
||||||
const ssr = options?.ssr === true;
|
const ssr = options?.ssr === true;
|
||||||
if (!ssr) return source;
|
|
||||||
if (!source.includes('import.meta')) return source;
|
if(!ssr) {
|
||||||
if (!/\benv\b/.test(source)) return source;
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!source.includes('import.meta') || !/\benv\b/.test(source)) {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof privateEnv === 'undefined') {
|
if (typeof privateEnv === 'undefined') {
|
||||||
privateEnv = getPrivateEnv(config, astroConfig);
|
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
|
||||||
|
'(?<!(?<!\\.\\.)\\.)\\b(' +
|
||||||
|
Object.keys(replacements)
|
||||||
|
.map((str) => {
|
||||||
|
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;
|
if (!referencesPrivateKey(source, privateEnv)) return source;
|
||||||
|
|
||||||
|
// Find matches for *private* env and do our own replacement.
|
||||||
const s = new MagicString(source);
|
const s = new MagicString(source);
|
||||||
// prettier-ignore
|
let match: RegExpExecArray | null
|
||||||
s.prepend(`import.meta.env = new Proxy(import.meta.env, {` +
|
|
||||||
`get(target, prop, reciever) {` +
|
while ((match = pattern.exec(source))) {
|
||||||
`const PRIVATE = ${JSON.stringify(privateEnv)};` +
|
const start = match.index
|
||||||
`if (typeof PRIVATE[prop] !== 'undefined') {` +
|
const end = start + match[0].length
|
||||||
`return PRIVATE[prop];` +
|
const replacement = '' + replacements[match[1]]
|
||||||
`}` +
|
s.overwrite(start, end, replacement)
|
||||||
`return Reflect.get(target, prop, reciever);` +
|
}
|
||||||
`}` +
|
|
||||||
`});\n`);
|
|
||||||
|
|
||||||
return s.toString();
|
return s.toString();
|
||||||
},
|
},
|
||||||
|
|
|
@ -15,12 +15,17 @@ describe('CSS', function () {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
projectRoot: './fixtures/0-css/',
|
projectRoot: './fixtures/0-css/',
|
||||||
renderers: ['@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'],
|
renderers: ['@astrojs/renderer-react', '@astrojs/renderer-svelte', '@astrojs/renderer-vue'],
|
||||||
|
vite: {
|
||||||
|
build: {
|
||||||
|
assetsInlineLimit: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// test HTML and CSS contents for accuracy
|
// test HTML and CSS contents for accuracy
|
||||||
describe('build', () => {
|
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 $;
|
||||||
let bundledCSS;
|
let bundledCSS;
|
||||||
|
@ -31,7 +36,7 @@ describe('CSS', function () {
|
||||||
// get bundled CSS (will be hashed, hence DOM query)
|
// get bundled CSS (will be hashed, hence DOM query)
|
||||||
const html = await fixture.readFile('/index.html');
|
const html = await fixture.readFile('/index.html');
|
||||||
$ = cheerio.load(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(/^\/?/, '/'));
|
bundledCSS = await fixture.readFile(bundledCSSHREF.replace(/^\/?/, '/'));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -47,7 +52,8 @@ describe('CSS', function () {
|
||||||
expect(el2.attr('class')).to.equal(`visible ${scopedClass}`);
|
expect(el2.attr('class')).to.equal(`visible ${scopedClass}`);
|
||||||
|
|
||||||
// 2. check CSS
|
// 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 <style> skips scoping', async () => {
|
it('No <style> skips scoping', async () => {
|
||||||
|
@ -60,7 +66,8 @@ describe('CSS', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Using hydrated components adds astro-root styles', async () => {
|
it('Using hydrated components adds astro-root styles', async () => {
|
||||||
expect(bundledCSS).to.include('display:contents');
|
const inline = $('style').html();
|
||||||
|
expect(inline).to.include('display: contents');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('<style lang="sass">', async () => {
|
it('<style lang="sass">', async () => {
|
||||||
|
@ -217,7 +224,7 @@ describe('CSS', function () {
|
||||||
it('<style>', async () => {
|
it('<style>', async () => {
|
||||||
const el = $('#svelte-css');
|
const el = $('#svelte-css');
|
||||||
const classes = el.attr('class').split(' ');
|
const classes = el.attr('class').split(' ');
|
||||||
const scopedClass = classes.find((name) => /^s-[A-Za-z0-9-]+/.test(name));
|
const scopedClass = classes.find((name) => name !== 'svelte-css' && /^svelte-[A-Za-z0-9-]+/.test(name));
|
||||||
|
|
||||||
// 1. check HTML
|
// 1. check HTML
|
||||||
expect(el.attr('class')).to.include('svelte-css');
|
expect(el.attr('class')).to.include('svelte-css');
|
||||||
|
@ -229,7 +236,7 @@ describe('CSS', function () {
|
||||||
it('<style lang="sass">', async () => {
|
it('<style lang="sass">', async () => {
|
||||||
const el = $('#svelte-sass');
|
const el = $('#svelte-sass');
|
||||||
const classes = el.attr('class').split(' ');
|
const classes = el.attr('class').split(' ');
|
||||||
const scopedClass = classes.find((name) => /^s-[A-Za-z0-9-]+/.test(name));
|
const scopedClass = classes.find((name) => name !== 'svelte-sass' && /^svelte-[A-Za-z0-9-]+/.test(name));
|
||||||
|
|
||||||
// 1. check HTML
|
// 1. check HTML
|
||||||
expect(el.attr('class')).to.include('svelte-sass');
|
expect(el.attr('class')).to.include('svelte-sass');
|
||||||
|
@ -241,7 +248,7 @@ describe('CSS', function () {
|
||||||
it('<style lang="scss">', async () => {
|
it('<style lang="scss">', async () => {
|
||||||
const el = $('#svelte-scss');
|
const el = $('#svelte-scss');
|
||||||
const classes = el.attr('class').split(' ');
|
const classes = el.attr('class').split(' ');
|
||||||
const scopedClass = classes.find((name) => /^s-[A-Za-z0-9-]+/.test(name));
|
const scopedClass = classes.find((name) => name !== 'svelte-scss' && /^svelte-[A-Za-z0-9-]+/.test(name));
|
||||||
|
|
||||||
// 1. check HTML
|
// 1. check HTML
|
||||||
expect(el.attr('class')).to.include('svelte-scss');
|
expect(el.attr('class')).to.include('svelte-scss');
|
||||||
|
@ -272,11 +279,6 @@ describe('CSS', function () {
|
||||||
expect((await fixture.fetch(href)).status).to.equal(200);
|
expect((await fixture.fetch(href)).status).to.equal(200);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('resolves CSS in src/', async () => {
|
|
||||||
const href = $('link[href$="linked.css"]').attr('href');
|
|
||||||
expect((await fixture.fetch(href)).status).to.equal(200);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Skipped until upstream fix lands
|
// Skipped until upstream fix lands
|
||||||
// Our fix: https://github.com/withastro/astro/pull/2106
|
// Our fix: https://github.com/withastro/astro/pull/2106
|
||||||
// OG Vite PR: https://github.com/vitejs/vite/pull/5940
|
// OG Vite PR: https://github.com/vitejs/vite/pull/5940
|
||||||
|
|
|
@ -11,7 +11,14 @@ describe('Assets', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-assets/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-assets/',
|
||||||
|
vite: {
|
||||||
|
build: {
|
||||||
|
assetsInlineLimit: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,7 +26,7 @@ describe('Assets', () => {
|
||||||
const html = await fixture.readFile('/index.html');
|
const html = await fixture.readFile('/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
const imgPath = $('img').attr('src');
|
const imgPath = $('img').attr('src');
|
||||||
const data = await fixture.readFile('/' + imgPath);
|
const data = await fixture.readFile( imgPath);
|
||||||
expect(!!data).to.equal(true);
|
expect(!!data).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,7 +36,7 @@ describe('Assets', () => {
|
||||||
const srcset = $('img').attr('srcset');
|
const srcset = $('img').attr('srcset');
|
||||||
const candidates = matchSrcset(srcset);
|
const candidates = matchSrcset(srcset);
|
||||||
const match = candidates.find((a) => a.density === 2);
|
const match = candidates.find((a) => a.density === 2);
|
||||||
const data = await fixture.readFile('/' + match.url);
|
const data = await fixture.readFile(match.url);
|
||||||
expect(!!data).to.equal(true);
|
expect(!!data).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -39,14 +46,14 @@ describe('Assets', () => {
|
||||||
const srcset = $('img').attr('srcset');
|
const srcset = $('img').attr('srcset');
|
||||||
const candidates = matchSrcset(srcset);
|
const candidates = matchSrcset(srcset);
|
||||||
const match = candidates.find((a) => a.density === 3);
|
const match = candidates.find((a) => a.density === 3);
|
||||||
const data = await fixture.readFile('/' + match.url);
|
const data = await fixture.readFile(match.url);
|
||||||
expect(!!data).to.equal(true);
|
expect(!!data).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('built image from an import specifier', async () => {
|
it('built image from an import specifier', async () => {
|
||||||
const html = await fixture.readFile('/index.html');
|
const html = await fixture.readFile('/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
const src = '/' + $('#import-no-url').attr('src');
|
const src = $('#import-no-url').attr('src');
|
||||||
const data = await fixture.readFile(src);
|
const data = await fixture.readFile(src);
|
||||||
expect(!!data).to.equal(true);
|
expect(!!data).to.equal(true);
|
||||||
});
|
});
|
||||||
|
@ -54,7 +61,7 @@ describe('Assets', () => {
|
||||||
it('built image from an import specifier using ?url', async () => {
|
it('built image from an import specifier using ?url', async () => {
|
||||||
const html = await fixture.readFile('/index.html');
|
const html = await fixture.readFile('/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
const src = '/' + $('#import-url').attr('src');
|
const src = $('#import-url').attr('src');
|
||||||
const data = await fixture.readFile(src);
|
const data = await fixture.readFile(src);
|
||||||
expect(!!data).to.equal(true);
|
expect(!!data).to.equal(true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,7 +7,9 @@ describe('Astro basics', () => {
|
||||||
let previewServer;
|
let previewServer;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-basic/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-basic/',
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
previewServer = await fixture.preview();
|
previewServer = await fixture.preview();
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,9 @@ describe('Client only components', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-client-only/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-client-only/',
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -16,19 +18,10 @@ describe('Client only components', () => {
|
||||||
|
|
||||||
// test 1: <astro-root> is empty
|
// test 1: <astro-root> is empty
|
||||||
expect($('astro-root').html()).to.equal('');
|
expect($('astro-root').html()).to.equal('');
|
||||||
const src = $('script').attr('src');
|
const $script = $('script');
|
||||||
|
const script = $script.html();
|
||||||
|
|
||||||
const script = await fixture.readFile(src);
|
|
||||||
// test 2: svelte renderer is on the page
|
// test 2: svelte renderer is on the page
|
||||||
const exp = /import\("(.\/client.*)"\)/g;
|
expect(/import\(".\/PersistentCounter.*/g.test(script)).to.be.ok;
|
||||||
let match, svelteRenderer;
|
|
||||||
while ((match = exp.exec(script))) {
|
|
||||||
svelteRenderer = match[1].replace(/^\./, '/assets/');
|
|
||||||
}
|
|
||||||
expect(svelteRenderer).to.be.ok;
|
|
||||||
|
|
||||||
// test 3: can load svelte renderer
|
|
||||||
const svelteClient = await fixture.readFile(svelteRenderer);
|
|
||||||
expect(svelteClient).to.be.ok;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
/**
|
|
||||||
* UNCOMMENT: add support for functional components in frontmatter
|
|
||||||
import { expect } from 'chai';
|
|
||||||
import cheerio from 'cheerio';
|
|
||||||
import { loadFixture } from './test-utils.js';
|
|
||||||
|
|
||||||
let fixture;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-components/' });
|
|
||||||
await fixture.build();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: add support for functional components in frontmatter
|
|
||||||
describe('Components tests', () => {
|
|
||||||
it('Astro components are able to render framework components', async () => {
|
|
||||||
const html = await fixture.readFile('/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
// test 1: Renders Astro component
|
|
||||||
const $astro = $('#astro');
|
|
||||||
expect($astro.children()).to.have.lengthOf(3);
|
|
||||||
|
|
||||||
// test 2: Renders React component
|
|
||||||
const $react = $('#react');
|
|
||||||
expect($react).not.to.have.lengthOf(0);
|
|
||||||
|
|
||||||
// test 3: Renders Vue component
|
|
||||||
const $vue = $('#vue');
|
|
||||||
expect($vue).not.to.have.lengthOf(0);
|
|
||||||
|
|
||||||
// test 4: Renders Svelte component
|
|
||||||
const $svelte = $('#svelte');
|
|
||||||
expect($svelte).not.to.have.lengthOf(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Allows Components defined in frontmatter', async () => {
|
|
||||||
const html = await fixture.readFile('/frontmatter-component/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1')).to.have.lengthOf(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Still throws an error for undefined components', async () => {
|
|
||||||
const result = await fixture.readFile('/undefined-component/index.html');
|
|
||||||
expect(result.status).to.equal(500);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Client attrs not added', async () => {
|
|
||||||
const html = await fixture.readFile('/client/index.html');
|
|
||||||
expect(html).not.to.include(`"client:load": true`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
it.skip('is skipped', () => {});
|
|
|
@ -6,7 +6,9 @@ describe('CSS Bundling (ESM import)', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-css-bundling-import/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-css-bundling-import/',
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -32,8 +34,7 @@ describe('CSS Bundling (ESM import)', () => {
|
||||||
expect(css.indexOf('p{color:green}')).to.be.greaterThan(css.indexOf('p{color:#00f}'));
|
expect(css.indexOf('p{color:green}')).to.be.greaterThan(css.indexOf('p{color:#00f}'));
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: re-enable this
|
it('no empty CSS files', async () => {
|
||||||
it.skip('no empty CSS files', async () => {
|
|
||||||
for (const page of ['/page-1/index.html', '/page-2/index.html']) {
|
for (const page of ['/page-1/index.html', '/page-2/index.html']) {
|
||||||
const html = await fixture.readFile(page);
|
const html = await fixture.readFile(page);
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import cheerio from 'cheerio';
|
|
||||||
import { loadFixture } from './test-utils.js';
|
|
||||||
|
|
||||||
describe('nested layouts', () => {
|
|
||||||
let fixture;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-css-bundling-nested-layouts/' });
|
|
||||||
await fixture.build();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('page-1 has all CSS', async () => {
|
|
||||||
const html = await fixture.readFile('/page-1/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
const stylesheets = $('link[rel=stylesheet]')
|
|
||||||
.toArray()
|
|
||||||
.map((el) => el.attribs.href);
|
|
||||||
|
|
||||||
// page-one.[hash].css exists
|
|
||||||
expect(stylesheets.some((href) => /page-one\.\w+\.css/.test(href))).to.be.true;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('page-2 has all CSS', async () => {
|
|
||||||
const html = await fixture.readFile('/page-2/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
const stylesheets = $('link[rel=stylesheet]')
|
|
||||||
.toArray()
|
|
||||||
.map((el) => el.attribs.href);
|
|
||||||
|
|
||||||
// page-one.[hash].css exists
|
|
||||||
expect(stylesheets.some((href) => /page-one\.\w+\.css/.test(href))).to.be.true;
|
|
||||||
// page-2.[hash].css exists
|
|
||||||
expect(stylesheets.some((href) => /page-2\.\w+\.css/.test(href))).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -5,11 +5,9 @@ import { loadFixture } from './test-utils.js';
|
||||||
// note: the hashes should be deterministic, but updating the file contents will change hashes
|
// note: the hashes should be deterministic, but updating the file contents will change hashes
|
||||||
// be careful not to test that the HTML simply contains CSS, because it always will! filename and quanity matter here (bundling).
|
// be careful not to test that the HTML simply contains CSS, because it always will! filename and quanity matter here (bundling).
|
||||||
const EXPECTED_CSS = {
|
const EXPECTED_CSS = {
|
||||||
'/index.html': ['./assets/index', './assets/typography'], // don’t match hashes, which change based on content
|
'/index.html': ['/assets/index'], // don’t match hashes, which change based on content
|
||||||
'/one/index.html': ['../assets/one'],
|
'/one/index.html': ['/assets/one'],
|
||||||
'/two/index.html': ['../assets/two', '../assets/typography'],
|
'/two/index.html': ['/assets/two'],
|
||||||
'/preload/index.html': ['../assets/preload'],
|
|
||||||
'/preload-merge/index.html': ['../assets/preload-merge'],
|
|
||||||
};
|
};
|
||||||
const UNEXPECTED_CSS = ['/src/components/nav.css', '../css/typography.css', '../css/colors.css', '../css/page-index.css', '../css/page-one.css', '../css/page-two.css'];
|
const UNEXPECTED_CSS = ['/src/components/nav.css', '../css/typography.css', '../css/colors.css', '../css/page-index.css', '../css/page-one.css', '../css/page-two.css'];
|
||||||
|
|
||||||
|
@ -17,7 +15,9 @@ describe('CSS Bundling', function () {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-css-bundling/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-css-bundling/',
|
||||||
|
});
|
||||||
await fixture.build({ mode: 'production' });
|
await fixture.build({ mode: 'production' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -43,21 +43,7 @@ describe('CSS Bundling', function () {
|
||||||
expect(link).to.have.lengthOf(0);
|
expect(link).to.have.lengthOf(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// test 3: preload tags was not removed and attributes was preserved
|
// test 3: assert all bundled CSS was built and contains CSS
|
||||||
if (filepath === '/preload/index.html') {
|
|
||||||
const stylesheet = $('link[rel="stylesheet"][href^="../assets/preload"]');
|
|
||||||
const preload = $('link[rel="preload"][href^="../assets/preload"]');
|
|
||||||
expect(stylesheet[0].attribs.media).to.equal('print');
|
|
||||||
expect(preload).to.have.lengthOf(1); // Preload tag was removed
|
|
||||||
}
|
|
||||||
|
|
||||||
// test 4: preload tags was not removed and attributes was preserved
|
|
||||||
if (filepath === '/preload-merge/index.html') {
|
|
||||||
const preload = $('link[rel="preload"]');
|
|
||||||
expect(preload).to.have.lengthOf(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// test 5: assert all bundled CSS was built and contains CSS
|
|
||||||
for (const url of builtCSS.keys()) {
|
for (const url of builtCSS.keys()) {
|
||||||
const css = await fixture.readFile(url);
|
const css = await fixture.readFile(url);
|
||||||
expect(css).to.be.ok;
|
expect(css).to.be.ok;
|
||||||
|
|
|
@ -6,7 +6,9 @@ describe('Dynamic components', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-dynamic/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-dynamic/',
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -14,7 +16,7 @@ describe('Dynamic components', () => {
|
||||||
const html = await fixture.readFile('/index.html');
|
const html = await fixture.readFile('/index.html');
|
||||||
|
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
expect($('script').length).to.eq(1);
|
expect($('script').length).to.eq(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Loads pages using client:media hydrator', async () => {
|
it('Loads pages using client:media hydrator', async () => {
|
||||||
|
@ -23,11 +25,7 @@ describe('Dynamic components', () => {
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
// test 1: static value rendered
|
// test 1: static value rendered
|
||||||
let js = await fixture.readFile(new URL($('script').attr('src'), root).pathname);
|
expect($('script').length).to.equal(2); // One for each
|
||||||
expect(js).to.include(`value:"(max-width: 700px)"`);
|
|
||||||
|
|
||||||
// test 2: dynamic value rendered
|
|
||||||
expect(js).to.include(`value:"(max-width: 600px)"`);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Loads pages using client:only hydrator', async () => {
|
it('Loads pages using client:only hydrator', async () => {
|
||||||
|
|
|
@ -5,7 +5,9 @@ describe('Environment Variables', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-envs/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-envs/',
|
||||||
|
});
|
||||||
|
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
@ -22,7 +24,7 @@ describe('Environment Variables', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('includes public env in client-side JS', async () => {
|
it('includes public env in client-side JS', async () => {
|
||||||
let dirs = await fixture.readdir('/assets');
|
let dirs = await fixture.readdir('/');
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
// Look in all of the .js files to see if the public env is inlined.
|
// Look in all of the .js files to see if the public env is inlined.
|
||||||
|
@ -31,7 +33,7 @@ describe('Environment Variables', () => {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
dirs.map(async (path) => {
|
dirs.map(async (path) => {
|
||||||
if (path.endsWith('.js')) {
|
if (path.endsWith('.js')) {
|
||||||
let js = await fixture.readFile(`/assets/${path}`);
|
let js = await fixture.readFile(`/${path}`);
|
||||||
if (js.includes('BLUE_BAYOU')) {
|
if (js.includes('BLUE_BAYOU')) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
@ -43,7 +45,7 @@ describe('Environment Variables', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not include private env in client-side JS', async () => {
|
it('does not include private env in client-side JS', async () => {
|
||||||
let dirs = await fixture.readdir('/assets');
|
let dirs = await fixture.readdir('/');
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
// Look in all of the .js files to see if the public env is inlined.
|
// Look in all of the .js files to see if the public env is inlined.
|
||||||
|
@ -52,7 +54,7 @@ describe('Environment Variables', () => {
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
dirs.map(async (path) => {
|
dirs.map(async (path) => {
|
||||||
if (path.endsWith('.js')) {
|
if (path.endsWith('.js')) {
|
||||||
let js = await fixture.readFile(`/assets/${path}`);
|
let js = await fixture.readFile(`/${path}`);
|
||||||
if (js.includes('CLUB_33')) {
|
if (js.includes('CLUB_33')) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ describe('Astro.*', () => {
|
||||||
projectRoot: './fixtures/astro-global/',
|
projectRoot: './fixtures/astro-global/',
|
||||||
buildOptions: {
|
buildOptions: {
|
||||||
site: 'https://mysite.dev/blog/',
|
site: 'https://mysite.dev/blog/',
|
||||||
sitemap: false,
|
sitemap: false
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
|
@ -48,13 +48,6 @@ describe('Astro.*', () => {
|
||||||
expect($('#site').attr('href')).to.equal('https://mysite.dev/blog/');
|
expect($('#site').attr('href')).to.equal('https://mysite.dev/blog/');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Astro.resolve built', async () => {
|
|
||||||
const html = await fixture.readFile('/resolve/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
expect($('img').attr('src')).to.include('assets/penguin.ccd44411.png'); // Main src/images
|
|
||||||
expect($('#inner-child img').attr('src')).to.include('assets/penguin.b9ab122a.png');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Astro.fetchContent() returns the correct "url" property, including buildOptions.site subpath', async () => {
|
it('Astro.fetchContent() returns the correct "url" property, including buildOptions.site subpath', async () => {
|
||||||
const html = await fixture.readFile('/posts/1/index.html');
|
const html = await fixture.readFile('/posts/1/index.html');
|
||||||
const $ = cheerio.load(html);
|
const $ = cheerio.load(html);
|
||||||
|
|
|
@ -7,7 +7,9 @@ describe('Partial HTML ', async () => {
|
||||||
let devServer;
|
let devServer;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-partial-html/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-partial-html/',
|
||||||
|
});
|
||||||
devServer = await fixture.startDevServer();
|
devServer = await fixture.startDevServer();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -23,7 +25,12 @@ describe('Partial HTML ', async () => {
|
||||||
expect(html).to.match(/^<!DOCTYPE html/);
|
expect(html).to.match(/^<!DOCTYPE html/);
|
||||||
|
|
||||||
// test 2: correct CSS present
|
// test 2: correct CSS present
|
||||||
const css = $('style[astro-style]').html();
|
const link = $('link').attr('href');
|
||||||
|
const css = await fixture.fetch(link, {
|
||||||
|
headers: {
|
||||||
|
accept: 'text/css'
|
||||||
|
}
|
||||||
|
}).then(res => res.text());
|
||||||
expect(css).to.match(/\.astro-[^{]+{color:red;}/);
|
expect(css).to.match(/\.astro-[^{]+{color:red;}/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,14 @@ describe('Scripts (hoisted and not)', () => {
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/astro-scripts/' });
|
fixture = await loadFixture({
|
||||||
|
projectRoot: './fixtures/astro-scripts/',
|
||||||
|
vite: {
|
||||||
|
build: {
|
||||||
|
assetsInlineLimit: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -38,8 +45,8 @@ describe('Scripts (hoisted and not)', () => {
|
||||||
// test 2: attr removed
|
// test 2: attr removed
|
||||||
expect($('script').attr('data-astro')).to.equal(undefined);
|
expect($('script').attr('data-astro')).to.equal(undefined);
|
||||||
|
|
||||||
let entryURL = path.join('inline', $('script').attr('src'));
|
const entryURL = $('script').attr('src');
|
||||||
let inlineEntryJS = await fixture.readFile(entryURL);
|
const inlineEntryJS = await fixture.readFile(entryURL);
|
||||||
|
|
||||||
// test 3: the JS exists
|
// test 3: the JS exists
|
||||||
expect(inlineEntryJS).to.be.ok;
|
expect(inlineEntryJS).to.be.ok;
|
||||||
|
@ -53,7 +60,7 @@ describe('Scripts (hoisted and not)', () => {
|
||||||
expect($('script')).to.have.lengthOf(2);
|
expect($('script')).to.have.lengthOf(2);
|
||||||
|
|
||||||
let el = $('script').get(1);
|
let el = $('script').get(1);
|
||||||
let entryURL = path.join('external', $(el).attr('src'));
|
let entryURL = $(el).attr('src');
|
||||||
let externalEntryJS = await fixture.readFile(entryURL);
|
let externalEntryJS = await fixture.readFile(entryURL);
|
||||||
|
|
||||||
// test 2: the JS exists
|
// test 2: the JS exists
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import cheerio from 'cheerio';
|
|
||||||
import { loadFixture } from './test-utils.js';
|
|
||||||
|
|
||||||
describe('Node builtins', () => {
|
|
||||||
let fixture;
|
|
||||||
|
|
||||||
before(async () => {
|
|
||||||
fixture = await loadFixture({ projectRoot: './fixtures/builtins/' });
|
|
||||||
await fixture.build();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can be used with the node: prefix', async () => {
|
|
||||||
const html = await fixture.readFile('/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('#version').text()).to.equal('1.2.0');
|
|
||||||
expect($('#dep-version').text()).to.equal('0.1.0');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('Can also be used with the non-prefixed version', async () => {
|
|
||||||
const html = await fixture.readFile('/bare/index.html');
|
|
||||||
const $ = cheerio.load(html);
|
|
||||||
|
|
||||||
expect($('h1').text()).to.equal('true');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,51 +0,0 @@
|
||||||
import { expect } from 'chai';
|
|
||||||
import { cli } from './test-utils.js';
|
|
||||||
import { promises as fs } from 'fs';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
describe('astro cli', () => {
|
|
||||||
it('astro', async () => {
|
|
||||||
const proc = await cli();
|
|
||||||
|
|
||||||
expect(proc.stdout).to.include('astro - Futuristic web development tool');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('astro --version', async () => {
|
|
||||||
const pkgURL = new URL('../package.json', import.meta.url);
|
|
||||||
const pkgVersion = await fs.readFile(pkgURL, 'utf8').then((data) => JSON.parse(data).version);
|
|
||||||
|
|
||||||
const proc = await cli('--version');
|
|
||||||
|
|
||||||
expect(proc.stdout).to.equal(pkgVersion);
|
|
||||||
});
|
|
||||||
|
|
||||||
[undefined, '0.0.0.0', '127.0.0.1'].forEach((hostname) => {
|
|
||||||
it(`astro dev --hostname=${hostname}`, async () => {
|
|
||||||
const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
|
|
||||||
|
|
||||||
const hostnameArgs = hostname ? ['--hostname', hostname] : [];
|
|
||||||
const proc = cli('dev', '--project-root', fileURLToPath(projectRootURL), ...hostnameArgs);
|
|
||||||
|
|
||||||
let stdout = '';
|
|
||||||
|
|
||||||
for await (const chunk of proc.stdout) {
|
|
||||||
stdout += chunk;
|
|
||||||
|
|
||||||
if (chunk.includes('Local:')) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
proc.kill();
|
|
||||||
|
|
||||||
expect(stdout).to.include('Local: http://localhost:3000');
|
|
||||||
expect(stdout).to.include(`Network: http://${hostname ?? '127.0.0.1'}:3000`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('astro build', async () => {
|
|
||||||
const projectRootURL = new URL('./fixtures/astro-basic/', import.meta.url);
|
|
||||||
|
|
||||||
const proc = await cli('build', '--project-root', fileURLToPath(projectRootURL));
|
|
||||||
|
|
||||||
expect(proc.stdout).to.include('Done');
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -47,8 +47,8 @@ describe('Custom Elements', () => {
|
||||||
expect($('my-element template[shadowroot=open]')).to.have.lengthOf(1);
|
expect($('my-element template[shadowroot=open]')).to.have.lengthOf(1);
|
||||||
|
|
||||||
// Hydration
|
// Hydration
|
||||||
// test 3: Component and polyfill scripts bundled together
|
// test 3: Component and polyfill scripts bundled separately
|
||||||
expect($('script[type=module]')).to.have.lengthOf(1);
|
expect($('script[type=module]')).to.have.lengthOf(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Polyfills are added even if not hydrating', async () => {
|
it('Polyfills are added even if not hydrating', async () => {
|
||||||
|
|
|
@ -19,7 +19,7 @@ import VueScoped from '../components/VueScoped.vue';
|
||||||
import VueScss from '../components/VueScss.vue';
|
import VueScss from '../components/VueScss.vue';
|
||||||
import ReactDynamic from '../components/ReactDynamic.jsx';
|
import ReactDynamic from '../components/ReactDynamic.jsx';
|
||||||
|
|
||||||
import importedUrl from '../styles/imported-url.css?url';
|
import '../styles/imported-url.css';
|
||||||
---
|
---
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
@ -36,10 +36,15 @@ import importedUrl from '../styles/imported-url.css?url';
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link rel="stylesheet" type="text/css" href="/global.css">
|
<link rel="stylesheet" type="text/css" href="/global.css">
|
||||||
<link rel="stylesheet" type="text/css" href={Astro.resolve('../styles/linked.css')}>
|
<style>
|
||||||
<link rel="stylesheet" type="text/css" href={Astro.resolve('../styles/linked.scss')}>
|
@import '../styles/linked.css';
|
||||||
<link rel="stylesheet" type="text/css" href={Astro.resolve('../styles/linked.sass')}>
|
</style>
|
||||||
<link rel="stylesheet" type="text/css" href={importedUrl}>
|
<style lang="scss">
|
||||||
|
@import '../styles/linked.scss';
|
||||||
|
</style>
|
||||||
|
<style lang="sass">
|
||||||
|
@import '../styles/linked.sass'
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
|
|
@ -9,7 +9,7 @@ import p2Url from '../images/penguin2.jpg?url';
|
||||||
</style>
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<h1>Icons</h1>
|
<h1>Icons</h1>
|
||||||
<img src={Astro.resolve('../images/twitter.png')} srcset={`${Astro.resolve('../images/twitter.png')} 1x, ${Astro.resolve('../images/twitter@2x.png')} 2x, ${Astro.resolve('../images/twitter@3x.png')} 3x`} />
|
<img src={(await import('../images/twitter.png')).default} srcset={`${(await import('../images/twitter.png')).default} 1x, ${(await import('../images/twitter@2x.png')).default} 2x, ${(await import('../images/twitter@3x.png')).default} 3x`} />
|
||||||
<img srcset="https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg, https://ik.imagekit.io/demo/tr:w-450,h-450/medium_cafe_B1iTdD0C.jpg 600w, https://ik.imagekit.io/demo/tr:w-600,h-600/medium_cafe_B1iTdD0C.jpg 800w">
|
<img srcset="https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg, https://ik.imagekit.io/demo/tr:w-450,h-450/medium_cafe_B1iTdD0C.jpg 600w, https://ik.imagekit.io/demo/tr:w-600,h-600/medium_cafe_B1iTdD0C.jpg 800w">
|
||||||
<img srcset="https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg, https://ik.imagekit.io/demo/tr:w-450,h-450/medium_cafe_B1iTdD0C.jpg 1.5x, https://ik.imagekit.io/demo/tr:w-600,h-600/medium_cafe_B1iTdD0C.jpg 2x">
|
<img srcset="https://ik.imagekit.io/demo/tr:w-300,h-300/medium_cafe_B1iTdD0C.jpg, https://ik.imagekit.io/demo/tr:w-450,h-450/medium_cafe_B1iTdD0C.jpg 1.5x, https://ik.imagekit.io/demo/tr:w-600,h-600/medium_cafe_B1iTdD0C.jpg 2x">
|
||||||
<!--
|
<!--
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
import ReactComponent from './Component.jsx';
|
|
||||||
import VueComponent from './Component.vue';
|
|
||||||
import SvelteComponent from './Component.svelte';
|
|
||||||
---
|
|
||||||
|
|
||||||
<div id="astro">
|
|
||||||
<ReactComponent />
|
|
||||||
<VueComponent />
|
|
||||||
<SvelteComponent />
|
|
||||||
</div>
|
|
|
@ -1,5 +0,0 @@
|
||||||
import { h } from 'preact';
|
|
||||||
|
|
||||||
export default function PreactComponent({ children }) {
|
|
||||||
return <div id="preact">{children}</div>;
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
<div id="svelte">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
|
@ -1,9 +0,0 @@
|
||||||
<template>
|
|
||||||
<div id="vue">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {}
|
|
||||||
</script>
|
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
export interface Props {
|
|
||||||
test: string;
|
|
||||||
}
|
|
||||||
---
|
|
||||||
<h1 id="direct-props-h1">{props.test}</h1>
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
import SvelteComponent from '../components/Component.svelte';
|
|
||||||
---
|
|
||||||
<html>
|
|
||||||
<head><title>Components</title></head>
|
|
||||||
<body>
|
|
||||||
<SvelteComponent client:load />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
const { level = 1 } = Astro.props;
|
|
||||||
const Element = `h${level}`;
|
|
||||||
---
|
|
||||||
|
|
||||||
<Element>Hello world!</Element>
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
import AstroComponent from '../components/Component.astro';
|
|
||||||
---
|
|
||||||
<html>
|
|
||||||
<head><title>Components</title></head>
|
|
||||||
<body>
|
|
||||||
<AstroComponent />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,4 +0,0 @@
|
||||||
---
|
|
||||||
import PropsComponent from "../components/Props-Component.astro"
|
|
||||||
---
|
|
||||||
<PropsComponent test="test string"/>
|
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
function FnComponent() {
|
|
||||||
const lame = 'ugh';
|
|
||||||
return <h2>Hey</h2>
|
|
||||||
}
|
|
||||||
const Defined = 'h1'
|
|
||||||
---
|
|
||||||
|
|
||||||
<FnComponent />
|
|
||||||
<Defined>Hello world!</Defined>
|
|
||||||
<Undefined />
|
|
|
@ -1,27 +0,0 @@
|
||||||
---
|
|
||||||
import "../styles/site.css"
|
|
||||||
|
|
||||||
const {title} = Astro.props;
|
|
||||||
---
|
|
||||||
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
||||||
<meta name="viewport" content="width=device-width" />
|
|
||||||
<title>{title}</title>
|
|
||||||
<style>
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<ul>
|
|
||||||
<li><a href="/page-1">Page 1</a></li>
|
|
||||||
<li><a href="/page-2">Page 2</a></li>
|
|
||||||
<!-- <li><a href="/page-2-reduced-layout">Page 2 reduced layout</a></li> -->
|
|
||||||
</ul>
|
|
||||||
<slot></slot>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
|
@ -1,12 +0,0 @@
|
||||||
---
|
|
||||||
import BaseLayout from "./BaseLayout.astro"
|
|
||||||
import "../styles/page-one.css"
|
|
||||||
|
|
||||||
const {title} = Astro.props;
|
|
||||||
---
|
|
||||||
|
|
||||||
<BaseLayout title={title}>
|
|
||||||
<main id="page">
|
|
||||||
<slot></slot>
|
|
||||||
</main>
|
|
||||||
</BaseLayout>
|
|
|
@ -1,15 +0,0 @@
|
||||||
---
|
|
||||||
import PageLayout from "../layouts/PageLayout.astro"
|
|
||||||
|
|
||||||
const date = new Date();
|
|
||||||
---
|
|
||||||
|
|
||||||
<PageLayout title="Page 1">
|
|
||||||
<h1>Page 1</h1>
|
|
||||||
<p>This page has styling in dev-server. But the built page has no styling. </p>
|
|
||||||
<p>Check <code>dist/page-1/index.html</code>. There are no stylesheets imported.</p>
|
|
||||||
<p>Additionally, there is an empty js file in the <code>dist/assets</code> folder. Thankfully the file is not required by any page.</p>
|
|
||||||
<p>Execute the build <code>npm run build</code> and preview it <code>npx http-server dist/</code> at <a href="https://github-qoihup--8080.local.webcontainer.io/page-1/">https://github-qoihup--8080.local.webcontainer.io/page-1/</a></p>
|
|
||||||
|
|
||||||
<p>Date: {date}</p>
|
|
||||||
</PageLayout>
|
|
|
@ -1,9 +0,0 @@
|
||||||
---
|
|
||||||
import PageLayout from "../layouts/PageLayout.astro"
|
|
||||||
import "../styles/page-two.css"
|
|
||||||
---
|
|
||||||
|
|
||||||
<PageLayout title="Page 2">
|
|
||||||
<h1>Page 2</h1>
|
|
||||||
<p>Nothing to see here. Check <a href="/page-1">Page 1</a></p>
|
|
||||||
</PageLayout>
|
|
|
@ -1,3 +0,0 @@
|
||||||
p {
|
|
||||||
color: blue;
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
p {
|
|
||||||
color: green;
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
p {
|
|
||||||
color: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
outline: 1px solid red;
|
|
||||||
}
|
|
|
@ -4,9 +4,11 @@ import Nav from '../components/Nav.astro';
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/typography.css')}>
|
<style>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/colors.css')}>
|
@import '../css/typography.css';
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-index.css')}>
|
@import '../css/colors.css';
|
||||||
|
@import '../css/page-index.css';
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Nav />
|
<Nav />
|
||||||
|
|
|
@ -4,8 +4,10 @@ import Nav from '../components/Nav.astro';
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/typography.css')} />
|
<style>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-one.css')} />
|
@import '../css/typography.css';
|
||||||
|
@import '../css/page-one.css';
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Nav />
|
<Nav />
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
---
|
|
||||||
import Nav from '../components/Nav.astro';
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="preload" as="style" href={Astro.resolve('../css/page-preload-merge.css')} />
|
|
||||||
<link rel="preload" as="style" href={Astro.resolve('../css/page-preload-merge-2.css')} />
|
|
||||||
|
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-preload-merge.css')} />
|
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-preload-merge-2.css')} />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<Nav />
|
|
||||||
<h1>Preload merge page</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
import Nav from '../components/Nav.astro';
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="preload" as="style" href={Astro.resolve('../css/page-preload.css')} />
|
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-preload.css')} media="print" onload="this.media='all'" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<Nav />
|
|
||||||
<h1>Preload page</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -4,9 +4,11 @@ import Nav from '../components/Nav.astro';
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/typography.css')} />
|
<style>
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/colors.css')} />
|
@import '../css/typography.css';
|
||||||
<link rel="stylesheet" href={Astro.resolve('../css/page-two.css')} />
|
@import '../css/colors.css';
|
||||||
|
@import '../css/page-two.css';
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Nav />
|
<Nav />
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
---
|
|
||||||
const penguinUrl = Astro.resolve('../images/penguin.png');
|
|
||||||
---
|
|
||||||
<img src={penguinUrl} />
|
|
||||||
<img src="../images/penguin.png" />
|
|
|
@ -1,6 +0,0 @@
|
||||||
---
|
|
||||||
const penguinUrl = Astro.resolve('./images/penguin.png');
|
|
||||||
---
|
|
||||||
<div id="inner-child">
|
|
||||||
<img src={penguinUrl} />
|
|
||||||
</div>
|
|
Binary file not shown.
Before Width: | Height: | Size: 76 KiB |
|
@ -1,14 +0,0 @@
|
||||||
---
|
|
||||||
import Child from '../components/ChildResolve.astro';
|
|
||||||
import InnerChild from '../components/nested/InnerChild.astro';
|
|
||||||
---
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Testing</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<Child />
|
|
||||||
<InnerChild />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue