mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-25 03:39:14 +00:00
Compare commits
30 Commits
@now/go@1.
...
@now/next@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb4d4b5953 | ||
|
|
de3701c045 | ||
|
|
9f9b7934cb | ||
|
|
bcded1dd17 | ||
|
|
8503af75ba | ||
|
|
158a50f1aa | ||
|
|
61da552dd6 | ||
|
|
fa838eecac | ||
|
|
71b6a58783 | ||
|
|
22dd78e286 | ||
|
|
e63fcf2630 | ||
|
|
98e1553c2e | ||
|
|
4dc506f17a | ||
|
|
3b396f29e9 | ||
|
|
1f128e69e6 | ||
|
|
f1487c92cb | ||
|
|
45066cdf44 | ||
|
|
7dde9c8207 | ||
|
|
fd964f825d | ||
|
|
1656c9874e | ||
|
|
d999a3b2ad | ||
|
|
cfb7c9e632 | ||
|
|
06e8472cf7 | ||
|
|
92404135d8 | ||
|
|
8b5cc23d7c | ||
|
|
e10b42bfdc | ||
|
|
36f7ec4836 | ||
|
|
f89d1c463e | ||
|
|
5dc652eba9 | ||
|
|
821b2bd50b |
4
.gitattributes
vendored
4
.gitattributes
vendored
@@ -1,3 +1,7 @@
|
||||
# Ignore test fixtures in GitHub Languages
|
||||
# See https://github.com/github/linguist#vendored-code
|
||||
packages/*/test/* linguist-vendored
|
||||
|
||||
# Go build fails with Windows line endings.
|
||||
*.go text eol=lf
|
||||
go.mod text eol=lf
|
||||
|
||||
2
.github/EXAMPLE_README_TEMPLATE.md
vendored
2
.github/EXAMPLE_README_TEMPLATE.md
vendored
@@ -6,7 +6,7 @@ This directory is a brief example of a [Name](site-link) site that can be deploy
|
||||
|
||||
Deploy your own [Name] project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now-examples/tree/master/example-directory)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now-examples/tree/master/example-directory)
|
||||
|
||||
### How We Created This Example
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ now # Deploy to the cloud
|
||||
|
||||
## Documentation
|
||||
|
||||
For details on how to use Now CLI, check out our [documentation](https://zeit.co/docs).
|
||||
For details on how to use Now CLI, check out our [documentation](https://zeit.co/docs/now-cli).
|
||||
|
||||
## Caught a Bug?
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of an [AMP](https://amp.dev/) site that can be
|
||||
|
||||
Deploy your own AMP project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/amp)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/amp)
|
||||
|
||||
_Live Example: https://amp.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of an [Angular](https://angular.io/) app that
|
||||
|
||||
Deploy your own Angular project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/angular)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/angular)
|
||||
|
||||
_Live Example: https://angular.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Assemble](http://assemble.io/) app that
|
||||
|
||||
Deploy your own Assemble project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/assemble)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/assemble)
|
||||
|
||||
_Live Example: https://assemble.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of an [Aurelia](https://aurelia.io/) app that
|
||||
|
||||
Deploy your own Aurelia project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/aurelia)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/aurelia)
|
||||
|
||||
_Live Example: https://aurelia.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Brunch](https://brunch.io/) site that ca
|
||||
|
||||
Deploy your own Brunch project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/brunch)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/brunch)
|
||||
|
||||
_Live Example: https://brunch.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Charge.js](https://charge.js.org/) site
|
||||
|
||||
Deploy your own Charge.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/charge)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/charge)
|
||||
|
||||
_Live Example: https://charge.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [React](https://reactjs.org/) app with [S
|
||||
|
||||
Deploy your own React project, along with Serverless Functions, with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/create-react-app-functions)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/create-react-app-functions)
|
||||
|
||||
_Live Example: https://create-react-app.now-examples.now.sh/_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of using a Custom Build script that can be dep
|
||||
|
||||
Deploy your own Custom Built project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/custom-build)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/custom-build)
|
||||
|
||||
_Live Example: https://custom-build.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Docusaurus](https://docusaurus.io/) site
|
||||
|
||||
Deploy your own Docusaurus project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/docusaurus)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/docusaurus)
|
||||
|
||||
_Live Example: https://docusaurus.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Docz](https://www.docz.site/) site that
|
||||
|
||||
Deploy your own Docz project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/docz)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/docz)
|
||||
|
||||
_Live Example: https://docz.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Eleventy](https://www.11ty.io/) site tha
|
||||
|
||||
Deploy your own Eleventy project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/eleventy)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/eleventy)
|
||||
|
||||
_Live Example: https://eleventy.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of an [Ember](https://emberjs.com/) app that c
|
||||
|
||||
Deploy your own Ember project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/ember)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/ember)
|
||||
|
||||
_Live Example: https://ember.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Foundation](https://foundation.zurb.com/
|
||||
|
||||
Deploy your own Foundation project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/foundation)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/foundation)
|
||||
|
||||
_Live Example: https://foundation.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Gatsby](https://www.gatsbyjs.org/) app w
|
||||
|
||||
Deploy your own Gatsby project, along with Serverless Functions, with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/gatsby)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/gatsby)
|
||||
|
||||
_Live Example: https://gatsby.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Gridsome](https://gridsome.org/) app tha
|
||||
|
||||
Deploy your own Gridsome project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/gridsome)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/gridsome)
|
||||
|
||||
_Live Example: https://gridsome.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Hexo](https://hexo.io/) site that can be
|
||||
|
||||
Deploy your own Hexo project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hexo)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hexo)
|
||||
|
||||
_Live Example: https://hexo.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Hugo](https://gohugo.io/) app that can b
|
||||
|
||||
Deploy your own Hugo project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hugo)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hugo)
|
||||
|
||||
_Live Example: https://hugo.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [HyperApp](https://github.com/jorgebucara
|
||||
|
||||
Deploy your own HyperApp project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hyperapp)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hyperapp)
|
||||
|
||||
_Live Example: https://hyperapp.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of an [Ionic React](https://ionicframework.com
|
||||
|
||||
Deploy your own Ionic React project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/ionic-react)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/ionic-react)
|
||||
|
||||
_Live Example: https://ionic-react.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Jekyll](https://jekyllrb.com/) site that
|
||||
|
||||
Deploy your own Jekyll project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/jekyll)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/jekyll)
|
||||
|
||||
_Live Example: https://jekyll.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Marko.js](https://markojs.com/) app that
|
||||
|
||||
Deploy your own Marko.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/marko)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/marko)
|
||||
|
||||
_Live Example: https://marko.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [mdx-deck](https://github.com/jxnblk/mdx-
|
||||
|
||||
Deploy your own mdx-deck project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mdx-deck)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/mdx-deck)
|
||||
|
||||
_Live Example: https://mdx-deck.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Metalsmith](https://metalsmith.io/) app
|
||||
|
||||
Deploy your own Metalsmith project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/metalsmith)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/metalsmith)
|
||||
|
||||
_Live Example: https://metalsmith.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Middleman](https://middlemanapp.com/) si
|
||||
|
||||
Deploy your own Middleman project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/middleman)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/middleman)
|
||||
|
||||
_Live Example: https://middleman.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Mithril](https://mithril.js.org/) app th
|
||||
|
||||
Deploy your own Mithril project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mithril)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/mithril)
|
||||
|
||||
_Live Example: https://mithril.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [MkDocs](https://www.mkdocs.org/) site th
|
||||
|
||||
Deploy your own MkDocs project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mkdocs)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/mkdocs)
|
||||
|
||||
_Live Example: https://mkdocs.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Next.js](https://nextjs.org) app that ca
|
||||
|
||||
Deploy your own Next.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/nextjs)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/nextjs)
|
||||
|
||||
_Live Example: https://nextjs.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Nuxt.js](https://nuxtjs.org) app that ca
|
||||
|
||||
Deploy your own Nuxt.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/nuxtjs)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/nuxtjs)
|
||||
|
||||
_Live Example: https://nuxtjs.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Pelican](https://docs.getpelican.com/en/
|
||||
|
||||
Deploy your own Pelican project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/pelican)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/pelican)
|
||||
|
||||
_Live Example: https://pelican.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Polymer](https://www.polymer-project.org
|
||||
|
||||
Deploy your own Polymer project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/polymer)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/polymer)
|
||||
|
||||
_Live Example: https://polymer.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Preact](https://preactjs.com/) app that
|
||||
|
||||
Deploy your own Preact project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/preact)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/preact)
|
||||
|
||||
_Live Example: https://preact.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Riot.js](https://riot.js.org/) app that
|
||||
|
||||
Deploy your own Riot.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/riot)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/riot)
|
||||
|
||||
_Live Example: https://riot.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Saber](https://saber.land) site that can
|
||||
|
||||
Deploy your own Saber project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/saber)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/saber)
|
||||
|
||||
_Live Example: https://saber.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Sapper](https://sapper.svelte.dev/) app
|
||||
|
||||
Deploy your own Sapper project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/sapper)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/sapper)
|
||||
|
||||
_Live Example: https://sapper.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Stencil](https://stenciljs.com/) app tha
|
||||
|
||||
Deploy your own Stencil project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/stencil)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/stencil)
|
||||
|
||||
_Live Example: https://stencil.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Storybook](https://storybook.js.org/) ap
|
||||
|
||||
Deploy your own Storybook project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/storybook)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/storybook)
|
||||
|
||||
_Live Example: https://storybook.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Svelte](https://svelte.dev/) app with [S
|
||||
|
||||
Deploy your own Svelte project, along with Serverless Functions, with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/svelte)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/svelte)
|
||||
|
||||
_Live Example: https://svelte.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [UmiJS](https://umijs.org/) app that can
|
||||
|
||||
Deploy your own UmiJS project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/umijs)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/umijs)
|
||||
|
||||
_Live Example: https://umijs.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a vanilla site that can be deployed with ZE
|
||||
|
||||
Deploy your own vanilla website, along with Serverless Functions, with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vanilla)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vanilla)
|
||||
|
||||
_Live Example: https://vanilla.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This directory is a brief example of a [Vue.js](https://vuejs.org/) app that can
|
||||
|
||||
Deploy your own Vue.js project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vue)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vue)
|
||||
|
||||
_Live Example: https://vue.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [VuePress](https://vuepress.vuejs.org/) a
|
||||
|
||||
Deploy your own VuePress project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vuepress)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vuepress)
|
||||
|
||||
_Live Example: https://vuepress.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ This directory is a brief example of a [Zola](https://www.getzola.org/) site tha
|
||||
|
||||
Deploy your own Zola project with ZEIT Now.
|
||||
|
||||
[](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/zola)
|
||||
[](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/zola)
|
||||
|
||||
_Live Example: https://zola.now-examples.now.sh_
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/build-utils",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.js",
|
||||
|
||||
@@ -80,6 +80,7 @@ export async function detectBuilders(
|
||||
warnings: ErrorResponse[];
|
||||
defaultRoutes: Route[] | null;
|
||||
redirectRoutes: Route[] | null;
|
||||
rewriteRoutes: Route[] | null;
|
||||
}> {
|
||||
const errors: ErrorResponse[] = [];
|
||||
const warnings: ErrorResponse[] = [];
|
||||
@@ -87,9 +88,6 @@ export async function detectBuilders(
|
||||
const apiBuilders: Builder[] = [];
|
||||
let frontendBuilder: Builder | null = null;
|
||||
|
||||
const defaultRoutes: Route[] = [];
|
||||
const redirectRoutes: Route[] = [];
|
||||
|
||||
const functionError = validateFunctions(options);
|
||||
|
||||
if (functionError) {
|
||||
@@ -99,6 +97,7 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
defaultRoutes: null,
|
||||
redirectRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,15 +130,15 @@ export async function detectBuilders(
|
||||
|
||||
let fallbackEntrypoint: string | null = null;
|
||||
|
||||
const preDefaultRoutes: Source[] = [];
|
||||
const preDynamicRoutes: Source[] = [];
|
||||
const apiRoutes: Source[] = [];
|
||||
const dynamicRoutes: Source[] = [];
|
||||
|
||||
// API
|
||||
for (const fileName of sortedFiles) {
|
||||
const apiBuilder = maybeGetApiBuilder(fileName, apiMatches, options);
|
||||
|
||||
if (apiBuilder) {
|
||||
const { routeError, defaultRoute, dynamicRoute } = getApiRoute(
|
||||
const { routeError, apiRoute, isDynamic } = getApiRoute(
|
||||
fileName,
|
||||
apiSortedFiles,
|
||||
options,
|
||||
@@ -153,15 +152,15 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
defaultRoutes: null,
|
||||
redirectRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
if (dynamicRoute) {
|
||||
preDynamicRoutes.push(dynamicRoute);
|
||||
}
|
||||
|
||||
if (defaultRoute) {
|
||||
preDefaultRoutes.push(defaultRoute);
|
||||
if (apiRoute) {
|
||||
apiRoutes.push(apiRoute);
|
||||
if (isDynamic) {
|
||||
dynamicRoutes.push(apiRoute);
|
||||
}
|
||||
}
|
||||
|
||||
addToUsedFunctions(apiBuilder);
|
||||
@@ -224,6 +223,7 @@ export async function detectBuilders(
|
||||
builders: null,
|
||||
redirectRoutes: null,
|
||||
defaultRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -264,6 +264,7 @@ export async function detectBuilders(
|
||||
warnings,
|
||||
redirectRoutes: null,
|
||||
defaultRoutes: null,
|
||||
rewriteRoutes: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -285,24 +286,22 @@ export async function detectBuilders(
|
||||
}
|
||||
}
|
||||
|
||||
const routesResult = mergeRoutes(
|
||||
preDefaultRoutes,
|
||||
preDynamicRoutes,
|
||||
const routesResult = getRouteResult(
|
||||
apiRoutes,
|
||||
dynamicRoutes,
|
||||
usedOutputDirectory,
|
||||
apiBuilders,
|
||||
frontendBuilder,
|
||||
options
|
||||
);
|
||||
|
||||
defaultRoutes.push(...routesResult.defaultRoutes);
|
||||
redirectRoutes.push(...routesResult.redirectRoutes);
|
||||
|
||||
return {
|
||||
warnings,
|
||||
builders: builders.length ? builders : null,
|
||||
errors: errors.length ? errors : null,
|
||||
redirectRoutes,
|
||||
defaultRoutes,
|
||||
redirectRoutes: routesResult.redirectRoutes,
|
||||
defaultRoutes: routesResult.defaultRoutes,
|
||||
rewriteRoutes: routesResult.rewriteRoutes,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -622,16 +621,16 @@ function getApiRoute(
|
||||
options: Options,
|
||||
absolutePathCache: Map<string, string>
|
||||
): {
|
||||
defaultRoute: Source | null;
|
||||
dynamicRoute: Source | null;
|
||||
apiRoute: Source | null;
|
||||
isDynamic: boolean;
|
||||
routeError: ErrorResponse | null;
|
||||
} {
|
||||
const conflictingSegment = getConflictingSegment(fileName);
|
||||
|
||||
if (conflictingSegment) {
|
||||
return {
|
||||
defaultRoute: null,
|
||||
dynamicRoute: null,
|
||||
apiRoute: null,
|
||||
isDynamic: false,
|
||||
routeError: {
|
||||
code: 'conflicting_path_segment',
|
||||
message:
|
||||
@@ -650,8 +649,8 @@ function getApiRoute(
|
||||
);
|
||||
|
||||
return {
|
||||
defaultRoute: null,
|
||||
dynamicRoute: null,
|
||||
apiRoute: null,
|
||||
isDynamic: false,
|
||||
routeError: {
|
||||
code: 'conflicting_file_path',
|
||||
message:
|
||||
@@ -669,8 +668,8 @@ function getApiRoute(
|
||||
);
|
||||
|
||||
return {
|
||||
defaultRoute: out.route,
|
||||
dynamicRoute: out.isDynamic ? out.route : null,
|
||||
apiRoute: out.route,
|
||||
isDynamic: out.isDynamic,
|
||||
routeError: null,
|
||||
};
|
||||
}
|
||||
@@ -835,10 +834,10 @@ function createRouteFromPath(
|
||||
} else if (isLast) {
|
||||
const { name: fileName, ext } = parsePath(segment);
|
||||
const isIndex = fileName === 'index';
|
||||
const prefix = isIndex ? '\\/' : '';
|
||||
const prefix = isIndex ? '/' : '';
|
||||
|
||||
const names = [
|
||||
isIndex ? prefix : `${fileName}\\/`,
|
||||
isIndex ? prefix : `${fileName}/`,
|
||||
prefix + escapeName(fileName),
|
||||
featHandleMiss && cleanUrls
|
||||
? ''
|
||||
@@ -881,9 +880,9 @@ function createRouteFromPath(
|
||||
return { route, isDynamic };
|
||||
}
|
||||
|
||||
function mergeRoutes(
|
||||
preDefaultRoutes: Source[],
|
||||
preDynamicRoutes: Source[],
|
||||
function getRouteResult(
|
||||
apiRoutes: Source[],
|
||||
dynamicRoutes: Source[],
|
||||
outputDirectory: string,
|
||||
apiBuilders: Builder[],
|
||||
frontendBuilder: Builder | null,
|
||||
@@ -891,14 +890,14 @@ function mergeRoutes(
|
||||
): {
|
||||
defaultRoutes: Route[];
|
||||
redirectRoutes: Route[];
|
||||
rewriteRoutes: Route[];
|
||||
} {
|
||||
const defaultRoutes: Route[] = [];
|
||||
const redirectRoutes: Route[] = [];
|
||||
const rewriteRoutes: Route[] = [];
|
||||
|
||||
if (preDefaultRoutes && preDefaultRoutes.length > 0) {
|
||||
if (apiRoutes && apiRoutes.length > 0) {
|
||||
if (options.featHandleMiss) {
|
||||
defaultRoutes.push({ handle: 'miss' });
|
||||
|
||||
const extSet = detectApiExtensions(apiBuilders);
|
||||
|
||||
if (extSet.size > 0) {
|
||||
@@ -923,6 +922,7 @@ function mergeRoutes(
|
||||
status: 308,
|
||||
});
|
||||
} else {
|
||||
defaultRoutes.push({ handle: 'miss' });
|
||||
defaultRoutes.push({
|
||||
src: `^/api/(.+)${extGroup}$`,
|
||||
dest: '/api/$1',
|
||||
@@ -931,21 +931,16 @@ function mergeRoutes(
|
||||
}
|
||||
}
|
||||
|
||||
if (preDynamicRoutes) {
|
||||
defaultRoutes.push(...preDynamicRoutes);
|
||||
}
|
||||
|
||||
if (preDefaultRoutes.length) {
|
||||
defaultRoutes.push({
|
||||
src: '^/api(/.*)?$',
|
||||
status: 404,
|
||||
continue: true,
|
||||
});
|
||||
}
|
||||
rewriteRoutes.push(...dynamicRoutes);
|
||||
rewriteRoutes.push({
|
||||
src: '^/api(/.*)?$',
|
||||
status: 404,
|
||||
continue: true,
|
||||
});
|
||||
} else {
|
||||
defaultRoutes.push(...preDefaultRoutes);
|
||||
defaultRoutes.push(...apiRoutes);
|
||||
|
||||
if (preDefaultRoutes.length) {
|
||||
if (apiRoutes.length) {
|
||||
defaultRoutes.push({
|
||||
status: 404,
|
||||
src: '^/api(/.*)?$',
|
||||
@@ -969,6 +964,7 @@ function mergeRoutes(
|
||||
return {
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -206,10 +206,10 @@ export async function runNpmInstall(
|
||||
debug(`Installing to ${destPath}`);
|
||||
const { hasPackageLockJson } = await scanParentDirs(destPath);
|
||||
|
||||
const opts = { cwd: destPath, ...spawnOpts } || {
|
||||
cwd: destPath,
|
||||
env: process.env,
|
||||
};
|
||||
const opts: SpawnOptions = { cwd: destPath, ...spawnOpts };
|
||||
const env = opts.env || { ...process.env };
|
||||
delete env.NODE_ENV;
|
||||
opts.env = env;
|
||||
|
||||
if (hasPackageLockJson) {
|
||||
commandArgs = args.filter(a => a !== '--prefer-offline');
|
||||
@@ -239,10 +239,7 @@ export async function runBundleInstall(
|
||||
}
|
||||
|
||||
assert(path.isAbsolute(destPath));
|
||||
const opts = { cwd: destPath, ...spawnOpts } || {
|
||||
cwd: destPath,
|
||||
env: process.env,
|
||||
};
|
||||
const opts = { cwd: destPath, ...spawnOpts };
|
||||
|
||||
await spawnAsync(
|
||||
'bundle',
|
||||
@@ -270,10 +267,7 @@ export async function runPipInstall(
|
||||
}
|
||||
|
||||
assert(path.isAbsolute(destPath));
|
||||
const opts = { cwd: destPath, ...spawnOpts } || {
|
||||
cwd: destPath,
|
||||
env: process.env,
|
||||
};
|
||||
const opts = { cwd: destPath, ...spawnOpts };
|
||||
|
||||
await spawnAsync(
|
||||
'pip3',
|
||||
|
||||
@@ -4,7 +4,7 @@ import FileRef from './file-ref';
|
||||
import { Lambda } from './lambda';
|
||||
|
||||
interface PrerenderOptions {
|
||||
expiration: number;
|
||||
expiration: number | false;
|
||||
lambda: Lambda;
|
||||
fallback: FileBlob | FileFsRef | FileRef | null;
|
||||
group?: number;
|
||||
@@ -13,7 +13,7 @@ interface PrerenderOptions {
|
||||
|
||||
export class Prerender {
|
||||
public type: 'Prerender';
|
||||
public expiration: number;
|
||||
public expiration: number | false;
|
||||
public lambda: Lambda;
|
||||
public fallback: FileBlob | FileFsRef | FileRef | null;
|
||||
public group?: number;
|
||||
|
||||
21
packages/now-build-utils/test/fixtures/16-node-env-install/build.js
vendored
Normal file
21
packages/now-build-utils/test/fixtures/16-node-env-install/build.js
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
function checkPkgOrThrow(pkgname) {
|
||||
try {
|
||||
const dep = require(pkgname);
|
||||
if (!dep) {
|
||||
throw new Error('Undefined');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(`Expected package "${pkgname}" to be installed.`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// We expect both `dependencies` and `devDependencies` to be installed
|
||||
// even when NODE_ENV=production.
|
||||
checkPkgOrThrow('tls-check');
|
||||
checkPkgOrThrow('exeggcute');
|
||||
|
||||
// This is to satisfy `@now/static-build` which needs a `dist` directory.
|
||||
const { exec } = require('exeggcute');
|
||||
exec('mkdir dist', __dirname);
|
||||
exec('echo "node-env:RANDOMNESS_PLACEHOLDER" > dist/index.html', __dirname);
|
||||
6
packages/now-build-utils/test/fixtures/16-node-env-install/now.json
vendored
Normal file
6
packages/now-build-utils/test/fixtures/16-node-env-install/now.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@now/static-build" }],
|
||||
"build": { "env": { "NODE_ENV": "production" } },
|
||||
"probes": [{ "path": "/", "mustContain": "node-env:RANDOMNESS_PLACEHOLDER" }]
|
||||
}
|
||||
12
packages/now-build-utils/test/fixtures/16-node-env-install/package.json
vendored
Normal file
12
packages/now-build-utils/test/fixtures/16-node-env-install/package.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "node build.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"tls-check": "1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"exeggcute": "1.0.0"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "now",
|
||||
"version": "17.0.4",
|
||||
"version": "17.0.5-canary.5",
|
||||
"preferGlobal": true,
|
||||
"license": "Apache-2.0",
|
||||
"description": "The command-line interface for Now",
|
||||
|
||||
@@ -566,6 +566,11 @@ export default async function main(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (deployment.readyState === 'CANCELED') {
|
||||
output.log('The deployment has been canceled');
|
||||
return 1;
|
||||
}
|
||||
|
||||
const deploymentResponse = await getDeploymentByIdOrHost(
|
||||
now,
|
||||
contextName,
|
||||
@@ -652,7 +657,12 @@ export default async function main(
|
||||
output.error('Build failed');
|
||||
output.error(
|
||||
`Check your logs at ${now.url}/_logs or run ${code(
|
||||
`now logs ${now.url}`
|
||||
`now logs ${now.url}`,
|
||||
{
|
||||
// Backticks are interpreted as part of the URL, causing CMD+Click
|
||||
// behavior to fail in editors like VSCode.
|
||||
backticks: false,
|
||||
}
|
||||
)}`
|
||||
);
|
||||
|
||||
|
||||
@@ -202,6 +202,13 @@ export default async function processDeployment({
|
||||
}
|
||||
}
|
||||
|
||||
if (event.type === 'canceled') {
|
||||
if (buildSpinner) {
|
||||
buildSpinner();
|
||||
}
|
||||
return event.payload;
|
||||
}
|
||||
|
||||
if (event.type === 'ready') {
|
||||
if (queuedSpinner) {
|
||||
queuedSpinner();
|
||||
|
||||
@@ -133,6 +133,9 @@ export async function devRouter(
|
||||
);
|
||||
if (missResult.found) {
|
||||
return missResult;
|
||||
} else {
|
||||
reqPathname = destPath;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (routeConfig.status && phase === 'miss') {
|
||||
|
||||
@@ -12,7 +12,11 @@ import serveHandler from 'serve-handler';
|
||||
import { watch, FSWatcher } from 'chokidar';
|
||||
import { parse as parseDotenv } from 'dotenv';
|
||||
import { basename, dirname, extname, join } from 'path';
|
||||
import { getTransformedRoutes, HandleValue } from '@now/routing-utils';
|
||||
import {
|
||||
getTransformedRoutes,
|
||||
appendRoutesToPhase,
|
||||
HandleValue,
|
||||
} from '@now/routing-utils';
|
||||
import directoryTemplate from 'serve-handler/src/directory';
|
||||
import getPort from 'get-port';
|
||||
import { ChildProcess } from 'child_process';
|
||||
@@ -553,6 +557,7 @@ export default class DevServer {
|
||||
errors,
|
||||
defaultRoutes,
|
||||
redirectRoutes,
|
||||
rewriteRoutes,
|
||||
} = await detectBuilders(files, pkg, {
|
||||
tag: getDistTag(cliVersion) === 'canary' ? 'canary' : 'latest',
|
||||
functions: config.functions,
|
||||
@@ -582,7 +587,13 @@ export default class DevServer {
|
||||
const routes: RouteConfig[] = [];
|
||||
const { routes: nowConfigRoutes } = config;
|
||||
routes.push(...(redirectRoutes || []));
|
||||
routes.push(...(nowConfigRoutes || []));
|
||||
routes.push(
|
||||
...appendRoutesToPhase({
|
||||
routes: nowConfigRoutes,
|
||||
newRoutes: rewriteRoutes,
|
||||
phase: 'filesystem',
|
||||
})
|
||||
);
|
||||
routes.push(...(defaultRoutes || []));
|
||||
config.routes = routes;
|
||||
}
|
||||
@@ -1176,6 +1187,35 @@ export default class DevServer {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This is the equivalent to now-proxy exit_with_status() function.
|
||||
*/
|
||||
exitWithStatus = async (
|
||||
match: BuildMatch | null,
|
||||
routeResult: RouteResult,
|
||||
phase: HandleValue | null,
|
||||
req: http.IncomingMessage,
|
||||
res: http.ServerResponse,
|
||||
nowRequestId: string
|
||||
): Promise<boolean> => {
|
||||
const { status, headers, dest } = routeResult;
|
||||
const location = headers['location'] || dest;
|
||||
|
||||
if (status && location && (300 <= status && status <= 399)) {
|
||||
this.output.debug(`Route found with redirect status code ${status}`);
|
||||
await this.sendRedirect(req, res, nowRequestId, location, status);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!match && status && phase !== 'miss') {
|
||||
this.output.debug(`Route found with with status code ${status}`);
|
||||
await this.sendError(req, res, nowRequestId, '', status);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Serve project directory as a Now v2 deployment.
|
||||
*/
|
||||
@@ -1259,6 +1299,19 @@ export default class DevServer {
|
||||
this
|
||||
);
|
||||
|
||||
if (
|
||||
await this.exitWithStatus(
|
||||
match,
|
||||
routeResult,
|
||||
phase,
|
||||
req,
|
||||
res,
|
||||
nowRequestId
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!match && missRoutes.length > 0) {
|
||||
// Since there was no build match, enter the miss phase
|
||||
routeResult = await devRouter(
|
||||
@@ -1277,6 +1330,18 @@ export default class DevServer {
|
||||
routeResult.dest,
|
||||
this
|
||||
);
|
||||
if (
|
||||
await this.exitWithStatus(
|
||||
match,
|
||||
routeResult,
|
||||
phase,
|
||||
req,
|
||||
res,
|
||||
nowRequestId
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
} else if (match && hitRoutes.length > 0) {
|
||||
// Since there was a build match, enter the hit phase.
|
||||
// The hit phase must not set status code.
|
||||
@@ -1295,28 +1360,6 @@ export default class DevServer {
|
||||
|
||||
statusCode = routeResult.status;
|
||||
|
||||
if (match && statusCode === 404 && routeResult.phase === 'miss') {
|
||||
statusCode = undefined;
|
||||
}
|
||||
|
||||
const location = routeResult.headers['location'] || routeResult.dest;
|
||||
|
||||
if (statusCode && location && (300 <= statusCode && statusCode <= 399)) {
|
||||
// Equivalent to now-proxy exit_with_status() function
|
||||
this.output.debug(
|
||||
`Route found with redirect status code ${statusCode}`
|
||||
);
|
||||
await this.sendRedirect(req, res, nowRequestId, location, statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!match && statusCode && routeResult.phase !== 'miss') {
|
||||
// Equivalent to now-proxy exit_with_status() function
|
||||
this.output.debug(`Route found with with status code ${statusCode}`);
|
||||
await this.sendError(req, res, nowRequestId, '', statusCode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (match) {
|
||||
// end the phase
|
||||
break;
|
||||
|
||||
@@ -4,6 +4,7 @@ import chalk from 'chalk';
|
||||
// The equivalent of <code>, for embedding anything
|
||||
// you may want to take a look at ./cmd.js
|
||||
|
||||
export default function code(cmd: string): string {
|
||||
return `${chalk.gray('`')}${chalk.bold(cmd)}${chalk.gray('`')}`;
|
||||
export default function code(cmd: string, { backticks = true } = {}): string {
|
||||
const tick = backticks ? chalk.gray('`') : '';
|
||||
return `${tick}${chalk.bold(cmd)}${tick}`;
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Index Page
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"routes": [
|
||||
{ "handle": "filesystem" },
|
||||
{ "src": "/([^/]+/dir/.+)", "dest": "/$1.html", "check": true },
|
||||
{ "handle": "miss" },
|
||||
{ "src": "/pathA(?:/.+)?", "status": 404, "continue": true },
|
||||
{ "src": "/pathB(?:/.+)?", "status": 404, "continue": true }
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Path A
|
||||
@@ -1 +0,0 @@
|
||||
Path B
|
||||
@@ -1 +0,0 @@
|
||||
Path C
|
||||
@@ -10,14 +10,14 @@
|
||||
"dest": "/blog/$1",
|
||||
"check": true
|
||||
},
|
||||
{
|
||||
"handle": "miss"
|
||||
},
|
||||
{
|
||||
"src": "/.*",
|
||||
"status": 404,
|
||||
"continue": true
|
||||
},
|
||||
{
|
||||
"handle": "miss"
|
||||
},
|
||||
{
|
||||
"src": "/(.*)",
|
||||
"dest": "/src/$1",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Index Page
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"version": 2,
|
||||
"routes": [
|
||||
{ "handle": "miss" },
|
||||
{ "src": "/pathA(?:/.+)?", "status": 404, "continue": true },
|
||||
{ "src": "/pathB(?:/.+)?", "status": 404, "continue": true }
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Path A
|
||||
@@ -1 +0,0 @@
|
||||
Path B
|
||||
@@ -1 +0,0 @@
|
||||
Path C
|
||||
@@ -1 +0,0 @@
|
||||
!public
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"functions": {
|
||||
"server/**/*.js": {
|
||||
"runtime": "@now/node@1.2.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
This is content.
|
||||
@@ -1,3 +0,0 @@
|
||||
export default (req, res) => {
|
||||
res.end(`current hour: ${Math.floor(Date.now() / 10000)}`);
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
module.exports = (req, res) =>
|
||||
res.send(req.query.username);
|
||||
@@ -0,0 +1 @@
|
||||
module.exports = (req, res) => res.end('42');
|
||||
@@ -0,0 +1,2 @@
|
||||
module.exports = (req, res) =>
|
||||
res.send(req.query.id);
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"rewrites": [{ "source": "/rand", "destination": "/api/fourty-two" }]
|
||||
}
|
||||
@@ -411,28 +411,6 @@ test(
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] does not display directory listing after multiple 404',
|
||||
testFixtureStdio('handle-miss-multiple-404', async (t, port) => {
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir`)).status, 200);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] does not display directory listing after `handle: miss` and 404',
|
||||
testFixtureStdio('handle-miss-handle-filesystem-404', async (t, port) => {
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir`)).status, 404);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir`)).status, 200);
|
||||
|
||||
t.is((await fetch(`http://localhost:${port}/pathA/dir/one`)).status, 200);
|
||||
t.is((await fetch(`http://localhost:${port}/pathB/dir/two`)).status, 200);
|
||||
t.is((await fetch(`http://localhost:${port}/pathC/dir/three`)).status, 200);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] handles hit after handle: filesystem',
|
||||
testFixtureStdio('handle-hit-after-fs', async (t, port) => {
|
||||
@@ -483,6 +461,8 @@ test(
|
||||
t.regex(await rand.text(), /random number/gm);
|
||||
const rand2 = await fetchWithRetry(`http://localhost:${port}/api/rand.js`);
|
||||
t.regex(await rand2.text(), /random number/gm);
|
||||
const notfound = await fetch(`http://localhost:${port}/api`);
|
||||
t.is(notfound.status, 404);
|
||||
})
|
||||
);
|
||||
|
||||
@@ -606,6 +586,31 @@ test('[now dev] validate env var names', async t => {
|
||||
t.pass();
|
||||
});
|
||||
|
||||
test(
|
||||
'[now dev] test rewrites with segments serve correct content',
|
||||
testFixtureStdio('test-rewrites-with-segments', async (t, port) => {
|
||||
const users = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/users/first`,
|
||||
3
|
||||
);
|
||||
t.regex(await users.text(), /first/gm);
|
||||
const fourtytwo = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/fourty-two`,
|
||||
3
|
||||
);
|
||||
t.regex(await fourtytwo.text(), /42/gm);
|
||||
const rand = await fetchWithRetry(`http://localhost:${port}/rand`, 3);
|
||||
t.regex(await rand.text(), /42/gm);
|
||||
const dynamic = await fetchWithRetry(
|
||||
`http://localhost:${port}/api/dynamic`,
|
||||
3
|
||||
);
|
||||
t.regex(await dynamic.text(), /dynamic/gm);
|
||||
const notfound = await fetch(`http://localhost:${port}/api`);
|
||||
t.is(notfound.status, 404);
|
||||
})
|
||||
);
|
||||
|
||||
test(
|
||||
'[now dev] test rewrites serve correct content',
|
||||
testFixtureStdio('test-rewrites', async (t, port) => {
|
||||
|
||||
@@ -156,33 +156,6 @@ RUN mkdir /public
|
||||
RUN echo hello > /public/index.html
|
||||
`,
|
||||
},
|
||||
'build-env': {
|
||||
'now.json': JSON.stringify({
|
||||
version: 1,
|
||||
type: 'static',
|
||||
build: {
|
||||
env: { FOO: 'bar' },
|
||||
},
|
||||
}),
|
||||
Dockerfile: `
|
||||
FROM alpine
|
||||
ARG FOO
|
||||
RUN mkdir /public
|
||||
RUN echo $FOO > /public/index.html
|
||||
`,
|
||||
},
|
||||
'build-env-arg': {
|
||||
'now.json': JSON.stringify({
|
||||
version: 1,
|
||||
type: 'static',
|
||||
}),
|
||||
Dockerfile: `
|
||||
FROM alpine
|
||||
ARG NONCE
|
||||
RUN mkdir /public
|
||||
RUN echo $NONCE > /public/index.html
|
||||
`,
|
||||
},
|
||||
'build-env-debug': {
|
||||
'now.json':
|
||||
'{ "builds": [ { "src": "index.js", "use": "@now/node" } ], "version": 2 }',
|
||||
|
||||
73
packages/now-cli/test/integration-v1.js
vendored
73
packages/now-cli/test/integration-v1.js
vendored
@@ -1859,79 +1859,6 @@ test('deploy a static build deployment', async t => {
|
||||
t.is(content.trim(), 'hello');
|
||||
});
|
||||
|
||||
test('use build-env', async t => {
|
||||
const directory = fixture('build-env');
|
||||
|
||||
const { stdout, stderr, exitCode } = await execa(
|
||||
binaryPath,
|
||||
[directory, '--public', '--name', session, ...defaultArgs],
|
||||
{
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
console.log(stderr);
|
||||
console.log(stdout);
|
||||
console.log(exitCode);
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(exitCode, 0);
|
||||
|
||||
// Test if the output is really a URL
|
||||
const deploymentUrl = pickUrl(stdout);
|
||||
const { href, host } = new URL(deploymentUrl);
|
||||
t.is(host.split('-')[0], session);
|
||||
|
||||
await waitForDeployment(href);
|
||||
|
||||
// get the content
|
||||
const response = await fetch(href);
|
||||
const content = await response.text();
|
||||
t.is(content.trim(), 'bar');
|
||||
});
|
||||
|
||||
test('use `--build-env` CLI flag', async t => {
|
||||
const directory = fixture('build-env-arg');
|
||||
const nonce = Math.random()
|
||||
.toString(36)
|
||||
.substring(2);
|
||||
|
||||
const { stderr, stdout, exitCode } = await execa(
|
||||
binaryPath,
|
||||
[
|
||||
directory,
|
||||
'--public',
|
||||
'--name',
|
||||
session,
|
||||
'--build-env',
|
||||
`NONCE=${nonce}`,
|
||||
...defaultArgs,
|
||||
],
|
||||
{
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
console.log(stderr);
|
||||
console.log(stdout);
|
||||
console.log(exitCode);
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(exitCode, 0, `Received:\n"${stderr}"\n"${stdout}"`);
|
||||
|
||||
// Test if the output is really a URL
|
||||
const deploymentUrl = pickUrl(stdout);
|
||||
const { href, host } = new URL(deploymentUrl);
|
||||
t.is(host.split('-')[0], session);
|
||||
|
||||
await waitForDeployment(href);
|
||||
|
||||
// get the content
|
||||
const response = await fetch(href);
|
||||
const content = await response.text();
|
||||
t.is(content.trim(), nonce);
|
||||
});
|
||||
|
||||
test('use `--debug` CLI flag', async t => {
|
||||
const directory = fixture('build-env-debug');
|
||||
|
||||
|
||||
74
packages/now-cli/test/integration.js
vendored
74
packages/now-cli/test/integration.js
vendored
@@ -1329,80 +1329,6 @@ test('deploying more than 1 path should fail', async t => {
|
||||
t.true(stderr.trim().endsWith(`Can't deploy more than one path.`));
|
||||
});
|
||||
|
||||
test('use build-env', async t => {
|
||||
const directory = fixture('build-env');
|
||||
|
||||
const { stdout, stderr, exitCode } = await execa(
|
||||
binaryPath,
|
||||
[directory, '--public', '--name', session, ...defaultArgs, '--confirm'],
|
||||
{
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
console.log(stderr);
|
||||
console.log(stdout);
|
||||
console.log(exitCode);
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(exitCode, 0);
|
||||
|
||||
// Test if the output is really a URL
|
||||
const deploymentUrl = pickUrl(stdout);
|
||||
const { href, host } = new URL(deploymentUrl);
|
||||
t.is(host.split('-')[0], session);
|
||||
|
||||
await waitForDeployment(href);
|
||||
|
||||
// get the content
|
||||
const response = await fetch(href);
|
||||
const content = await response.text();
|
||||
t.is(content.trim(), 'bar');
|
||||
});
|
||||
|
||||
test('use `--build-env` CLI flag', async t => {
|
||||
const directory = fixture('build-env-arg');
|
||||
const nonce = Math.random()
|
||||
.toString(36)
|
||||
.substring(2);
|
||||
|
||||
const { stderr, stdout, exitCode } = await execa(
|
||||
binaryPath,
|
||||
[
|
||||
directory,
|
||||
'--public',
|
||||
'--name',
|
||||
session,
|
||||
'--build-env',
|
||||
`NONCE=${nonce}`,
|
||||
...defaultArgs,
|
||||
'--confirm',
|
||||
],
|
||||
{
|
||||
reject: false,
|
||||
}
|
||||
);
|
||||
|
||||
console.log(stderr);
|
||||
console.log(stdout);
|
||||
console.log(exitCode);
|
||||
|
||||
// Ensure the exit code is right
|
||||
t.is(exitCode, 0, `Received:\n"${stderr}"\n"${stdout}"`);
|
||||
|
||||
// Test if the output is really a URL
|
||||
const deploymentUrl = pickUrl(stdout);
|
||||
const { href, host } = new URL(deploymentUrl);
|
||||
t.is(host.split('-')[0], session);
|
||||
|
||||
await waitForDeployment(href);
|
||||
|
||||
// get the content
|
||||
const response = await fetch(href);
|
||||
const content = await response.text();
|
||||
t.is(content.trim(), nonce);
|
||||
});
|
||||
|
||||
test('use `--debug` CLI flag', async t => {
|
||||
const directory = fixture('build-env-debug');
|
||||
|
||||
|
||||
4
packages/now-cli/test/unit.js
vendored
4
packages/now-cli/test/unit.js
vendored
@@ -69,9 +69,7 @@ const getStaticFiles = async (dir, isBuilds = false) => {
|
||||
const normalizeWindowsPaths = files => {
|
||||
if (process.platform === 'win32') {
|
||||
const prefix = 'D:/a/now/now/packages/now-cli/test/fixtures/unit/';
|
||||
return files.map(f =>
|
||||
f.replace(/\\/g, '/').slice(prefix.length)
|
||||
);
|
||||
return files.map(f => f.replace(/\\/g, '/').slice(prefix.length));
|
||||
}
|
||||
return files;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "now-client",
|
||||
"version": "7.0.0",
|
||||
"version": "7.0.1-canary.1",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"homepage": "https://zeit.co",
|
||||
|
||||
@@ -77,6 +77,15 @@ export async function* checkDeploymentStatus(
|
||||
yield { type: 'building', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (
|
||||
deploymentUpdate.readyState === 'CANCELED' &&
|
||||
!finishedEvents.has('canceled')
|
||||
) {
|
||||
debug('Deployment state changed to CANCELED');
|
||||
finishedEvents.add('canceled');
|
||||
yield { type: 'canceled', payload: deploymentUpdate };
|
||||
}
|
||||
|
||||
if (isReady(deploymentUpdate) && !finishedEvents.has('ready')) {
|
||||
debug('Deployment state changed to READY');
|
||||
finishedEvents.add('ready');
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DeploymentFile } from './hashes';
|
||||
import { parse as parseUrl } from 'url';
|
||||
import { FetchOptions } from '@zeit/fetch';
|
||||
import { nodeFetch, zeitFetch } from './fetch';
|
||||
import { join, sep } from 'path';
|
||||
import { join, sep, relative } from 'path';
|
||||
import qs from 'querystring';
|
||||
import ignore from 'ignore';
|
||||
import { pkgVersion } from '../pkg';
|
||||
@@ -29,6 +29,7 @@ const EVENTS_ARRAY = [
|
||||
'error',
|
||||
'notice',
|
||||
'tip',
|
||||
'canceled',
|
||||
] as const;
|
||||
|
||||
export type DeploymentEventType = (typeof EVENTS_ARRAY)[number];
|
||||
@@ -191,9 +192,10 @@ export const prepareFiles = (
|
||||
|
||||
if (clientOptions.isDirectory) {
|
||||
// Directory
|
||||
fileName = clientOptions.path
|
||||
? name.substring(clientOptions.path.length + 1)
|
||||
: name;
|
||||
fileName =
|
||||
typeof clientOptions.path === 'string'
|
||||
? relative(clientOptions.path, name)
|
||||
: name;
|
||||
} else {
|
||||
// Array of files or single file
|
||||
const segments = name.split(sep);
|
||||
|
||||
@@ -87,10 +87,12 @@ describe('create v2 deployment', () => {
|
||||
});
|
||||
|
||||
it('will create a v2 deployment with correct file permissions', async () => {
|
||||
let error = null;
|
||||
for await (const event of createDeployment(
|
||||
{
|
||||
token,
|
||||
path: path.resolve(__dirname, 'fixtures', 'v2-file-permissions'),
|
||||
skipAutoDetectionConfirmation: true,
|
||||
},
|
||||
{
|
||||
name: 'now-client-tests-v2',
|
||||
@@ -104,9 +106,16 @@ describe('create v2 deployment', () => {
|
||||
if (event.type === 'ready') {
|
||||
deployment = event.payload;
|
||||
break;
|
||||
} else if (event.type === 'error') {
|
||||
error = event.payload;
|
||||
console.error(error.message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
expect(error).toBe(null);
|
||||
expect(deployment.readyState).toEqual('READY');
|
||||
|
||||
const url = `https://${deployment.url}/api/index.js`;
|
||||
console.log('testing url ' + url);
|
||||
const response = await fetch_(url);
|
||||
@@ -116,10 +125,12 @@ describe('create v2 deployment', () => {
|
||||
});
|
||||
|
||||
it('will create a v2 deployment and ignore files specified in .nowignore', async () => {
|
||||
let error = null;
|
||||
for await (const event of createDeployment(
|
||||
{
|
||||
token,
|
||||
path: path.resolve(__dirname, 'fixtures', 'nowignore'),
|
||||
skipAutoDetectionConfirmation: true,
|
||||
},
|
||||
{
|
||||
name: 'now-client-tests-v2',
|
||||
@@ -132,11 +143,17 @@ describe('create v2 deployment', () => {
|
||||
)) {
|
||||
if (event.type === 'ready') {
|
||||
deployment = event.payload;
|
||||
expect(deployment.readyState).toEqual('READY');
|
||||
break;
|
||||
} else if (event.type === 'error') {
|
||||
error = event.payload;
|
||||
console.error(error.message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
expect(error).toBe(null);
|
||||
expect(deployment.readyState).toEqual('READY');
|
||||
|
||||
const index = await fetch_(`https://${deployment.url}`);
|
||||
expect(index.status).toBe(200);
|
||||
expect(await index.text()).toBe('Hello World!');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ncc build index.ts -o dist
|
||||
ncc build install.ts -o dist/install
|
||||
ncc build index.ts -e @now/build-utils -o dist
|
||||
ncc build install.ts -e @now/build-utils -o dist/install
|
||||
mv dist/install/index.js dist/install.js
|
||||
rm -rf dist/install
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/go",
|
||||
"version": "1.0.4",
|
||||
"version": "1.0.5-canary.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/go",
|
||||
|
||||
@@ -7,10 +7,10 @@ cp -v "$bridge_defs" src/now__bridge.ts
|
||||
|
||||
tsc
|
||||
|
||||
ncc build src/dev-server.ts -o dist/dev
|
||||
ncc build src/dev-server.ts -e @now/build-utils -o dist/dev
|
||||
mv dist/dev/index.js dist/dev-server.js
|
||||
rm -rf dist/dev
|
||||
|
||||
ncc build src/index.ts -o dist/main
|
||||
ncc build src/index.ts -e @now/build-utils -o dist/main
|
||||
mv dist/main/index.js dist/index.js
|
||||
rm -rf dist/main
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@now/next",
|
||||
"version": "2.3.16",
|
||||
"version": "2.4.0",
|
||||
"license": "MIT",
|
||||
"main": "./dist/index",
|
||||
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/next-js",
|
||||
|
||||
@@ -18,11 +18,11 @@ import {
|
||||
runNpmInstall,
|
||||
runPackageJsonScript,
|
||||
} from '@now/build-utils';
|
||||
import { Route, Source } from '@now/routing-utils';
|
||||
import { Route } from '@now/routing-utils';
|
||||
import {
|
||||
convertHeaders,
|
||||
convertRedirects,
|
||||
convertRewrites,
|
||||
convertHeaders,
|
||||
} from '@now/routing-utils/dist/superstatic';
|
||||
import nodeFileTrace, { NodeFileTraceReasons } from '@zeit/node-file-trace';
|
||||
import { ChildProcess, fork } from 'child_process';
|
||||
@@ -92,6 +92,8 @@ const nowDevChildProcesses = new Set<ChildProcess>();
|
||||
});
|
||||
});
|
||||
|
||||
const MAX_AGE_ONE_YEAR = 31536000;
|
||||
|
||||
/**
|
||||
* Read package.json from files
|
||||
*/
|
||||
@@ -334,11 +336,17 @@ export const build = async ({
|
||||
env.NODE_OPTIONS = `--max_old_space_size=${memoryToConsume}`;
|
||||
await runPackageJsonScript(entryPath, shouldRunScript, { ...spawnOpts, env });
|
||||
|
||||
const appMountPrefixNoTrailingSlash = path.posix
|
||||
.join('/', entryDirectory)
|
||||
.replace(/\/+$/, '');
|
||||
|
||||
const routesManifest = await getRoutesManifest(entryPath, realNextVersion);
|
||||
const prerenderManifest = await getPrerenderManifest(entryPath);
|
||||
const headers: Route[] = [];
|
||||
const rewrites: Route[] = [];
|
||||
const redirects: Route[] = [];
|
||||
const nextBasePathRoute: Route[] = [];
|
||||
const dataRoutes: Route[] = [];
|
||||
let nextBasePath: string | undefined;
|
||||
// whether they have enabled pages/404.js as the custom 404 page
|
||||
let hasPages404 = false;
|
||||
@@ -354,6 +362,40 @@ export const build = async ({
|
||||
headers.push(...convertHeaders(routesManifest.headers));
|
||||
}
|
||||
|
||||
if (routesManifest.dataRoutes) {
|
||||
// Load the /_next/data routes for both dynamic SSG and SSP pages.
|
||||
// These must be combined and sorted to prevent conflicts
|
||||
for (const dataRoute of routesManifest.dataRoutes) {
|
||||
const ssgDataRoute =
|
||||
prerenderManifest.fallbackRoutes[dataRoute.page] ||
|
||||
prerenderManifest.legacyBlockingRoutes[dataRoute.page];
|
||||
|
||||
// we don't need to add routes for non-lazy SSG routes since
|
||||
// they have outputs which would override the routes anyways
|
||||
if (
|
||||
prerenderManifest.staticRoutes[dataRoute.page] ||
|
||||
prerenderManifest.omittedRoutes.includes(dataRoute.page)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dataRoutes.push({
|
||||
src: dataRoute.dataRouteRegex.replace(
|
||||
/^\^/,
|
||||
`^${appMountPrefixNoTrailingSlash}`
|
||||
),
|
||||
dest: path.join(
|
||||
'/',
|
||||
entryDirectory,
|
||||
// make sure to route SSG data route to the data prerender
|
||||
// output, we don't do this for SSP routes since they don't
|
||||
// have a separate data output
|
||||
(ssgDataRoute && ssgDataRoute.dataRoute) || dataRoute.page
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (routesManifest.pages404) {
|
||||
hasPages404 = true;
|
||||
}
|
||||
@@ -455,7 +497,9 @@ export const build = async ({
|
||||
),
|
||||
// Next.js assets contain a hash or entropy in their filenames, so they
|
||||
// are guaranteed to be unique and cacheable indefinitely.
|
||||
headers: { 'cache-control': 'public,max-age=31536000,immutable' },
|
||||
headers: {
|
||||
'cache-control': `public,max-age=${MAX_AGE_ONE_YEAR},immutable`,
|
||||
},
|
||||
continue: true,
|
||||
},
|
||||
{
|
||||
@@ -517,13 +561,8 @@ export const build = async ({
|
||||
const prerenders: { [key: string]: Prerender | FileFsRef } = {};
|
||||
const staticPages: { [key: string]: FileFsRef } = {};
|
||||
const dynamicPages: string[] = [];
|
||||
const dynamicDataRoutes: Array<Source> = [];
|
||||
let static404Page: string | undefined;
|
||||
|
||||
const appMountPrefixNoTrailingSlash = path.posix
|
||||
.join('/', entryDirectory)
|
||||
.replace(/\/+$/, '');
|
||||
|
||||
if (isLegacy) {
|
||||
const filesAfterBuild = await glob('**', entryPath);
|
||||
|
||||
@@ -625,7 +664,6 @@ export const build = async ({
|
||||
|
||||
const pages = await glob('**/*.js', pagesDir);
|
||||
const staticPageFiles = await glob('**/*.html', pagesDir);
|
||||
const prerenderManifest = await getPrerenderManifest(entryPath);
|
||||
|
||||
Object.keys(staticPageFiles).forEach((page: string) => {
|
||||
const pathname = page.replace(/\.html$/, '');
|
||||
@@ -636,9 +674,8 @@ export const build = async ({
|
||||
// Lazily prerendered routes have a fallback `.html` file on newer
|
||||
// Next.js versions so we need to also not treat it as a static page here.
|
||||
if (
|
||||
prerenderManifest.routes[routeName] ||
|
||||
(prerenderManifest.lazyRoutes[routeName] &&
|
||||
prerenderManifest.lazyRoutes[routeName].fallback)
|
||||
prerenderManifest.staticRoutes[routeName] ||
|
||||
prerenderManifest.fallbackRoutes[routeName]
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -880,33 +917,49 @@ export const build = async ({
|
||||
}
|
||||
|
||||
let prerenderGroup = 1;
|
||||
const onPrerenderRoute = (routeKey: string, isLazy: boolean) => {
|
||||
const onPrerenderRoute = (
|
||||
routeKey: string,
|
||||
{ isBlocking, isFallback }: { isBlocking: boolean; isFallback: boolean }
|
||||
) => {
|
||||
if (isBlocking && isFallback) {
|
||||
throw new Error(
|
||||
'invariant: isBlocking and isFallback cannot both be true'
|
||||
);
|
||||
}
|
||||
|
||||
// Get the route file as it'd be mounted in the builder output
|
||||
const routeFileNoExt = routeKey === '/' ? '/index' : routeKey;
|
||||
const lazyHtmlFallback =
|
||||
isLazy && prerenderManifest.lazyRoutes[routeKey].fallback;
|
||||
|
||||
const htmlFsRef =
|
||||
isLazy && !lazyHtmlFallback
|
||||
const htmlFsRef = isBlocking
|
||||
? // Blocking pages do not have an HTML fallback
|
||||
null
|
||||
: new FileFsRef({
|
||||
fsPath: path.join(
|
||||
pagesDir,
|
||||
isFallback
|
||||
? // Fallback pages have a special file.
|
||||
prerenderManifest.fallbackRoutes[routeKey].fallback
|
||||
: // Otherwise, the route itself should exist as a static HTML
|
||||
// file.
|
||||
`${routeFileNoExt}.html`
|
||||
),
|
||||
});
|
||||
const jsonFsRef =
|
||||
// JSON data does not exist for fallback or blocking pages
|
||||
isFallback || isBlocking
|
||||
? null
|
||||
: new FileFsRef({
|
||||
fsPath: path.join(
|
||||
pagesDir,
|
||||
`${lazyHtmlFallback || routeFileNoExt + '.html'}`
|
||||
),
|
||||
fsPath: path.join(pagesDir, `${routeFileNoExt}.json`),
|
||||
});
|
||||
const jsonFsRef = isLazy
|
||||
? null
|
||||
: new FileFsRef({
|
||||
fsPath: path.join(pagesDir, `${routeFileNoExt}.json`),
|
||||
});
|
||||
|
||||
let initialRevalidate: false | number;
|
||||
let srcRoute: string | null;
|
||||
let dataRoute: string;
|
||||
|
||||
if (isLazy) {
|
||||
const pr = prerenderManifest.lazyRoutes[routeKey];
|
||||
if (isFallback || isBlocking) {
|
||||
const pr = isFallback
|
||||
? prerenderManifest.fallbackRoutes[routeKey]
|
||||
: prerenderManifest.legacyBlockingRoutes[routeKey];
|
||||
initialRevalidate = 1; // TODO: should Next.js provide this default?
|
||||
// @ts-ignore
|
||||
if (initialRevalidate === false) {
|
||||
@@ -916,7 +969,7 @@ export const build = async ({
|
||||
srcRoute = null;
|
||||
dataRoute = pr.dataRoute;
|
||||
} else {
|
||||
const pr = prerenderManifest.routes[routeKey];
|
||||
const pr = prerenderManifest.staticRoutes[routeKey];
|
||||
({ initialRevalidate, srcRoute, dataRoute } = pr);
|
||||
}
|
||||
|
||||
@@ -930,57 +983,64 @@ export const build = async ({
|
||||
);
|
||||
const outputPathData = path.posix.join(entryDirectory, dataRoute);
|
||||
|
||||
const lambda = lambdas[outputSrcPathPage];
|
||||
if (lambda == null) {
|
||||
throw new Error(`Unable to find lambda for route: ${routeFileNoExt}`);
|
||||
}
|
||||
|
||||
if (initialRevalidate === false) {
|
||||
if (htmlFsRef == null || jsonFsRef == null) {
|
||||
throw new Error('invariant: htmlFsRef != null && jsonFsRef != null');
|
||||
}
|
||||
htmlFsRef.contentType = htmlContentType;
|
||||
prerenders[outputPathPage] = htmlFsRef;
|
||||
prerenders[outputPathData] = jsonFsRef;
|
||||
} else {
|
||||
const lambda = lambdas[outputSrcPathPage];
|
||||
if (lambda == null) {
|
||||
throw new Error(`Unable to find lambda for route: ${routeFileNoExt}`);
|
||||
}
|
||||
|
||||
prerenders[outputPathPage] = new Prerender({
|
||||
expiration: initialRevalidate,
|
||||
lambda,
|
||||
fallback: htmlFsRef,
|
||||
group: prerenderGroup,
|
||||
bypassToken: prerenderManifest.bypassToken,
|
||||
});
|
||||
prerenders[outputPathData] = new Prerender({
|
||||
expiration: initialRevalidate,
|
||||
lambda,
|
||||
fallback: jsonFsRef,
|
||||
group: prerenderGroup,
|
||||
bypassToken: prerenderManifest.bypassToken,
|
||||
});
|
||||
|
||||
++prerenderGroup;
|
||||
}
|
||||
|
||||
prerenders[outputPathPage] = new Prerender({
|
||||
expiration: initialRevalidate,
|
||||
lambda,
|
||||
fallback: htmlFsRef,
|
||||
group: prerenderGroup,
|
||||
bypassToken: prerenderManifest.bypassToken,
|
||||
});
|
||||
prerenders[outputPathData] = new Prerender({
|
||||
expiration: initialRevalidate,
|
||||
lambda,
|
||||
fallback: jsonFsRef,
|
||||
group: prerenderGroup,
|
||||
bypassToken: prerenderManifest.bypassToken,
|
||||
});
|
||||
|
||||
++prerenderGroup;
|
||||
};
|
||||
|
||||
Object.keys(prerenderManifest.routes).forEach(route =>
|
||||
onPrerenderRoute(route, false)
|
||||
Object.keys(prerenderManifest.staticRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, { isBlocking: false, isFallback: false })
|
||||
);
|
||||
Object.keys(prerenderManifest.lazyRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, true)
|
||||
Object.keys(prerenderManifest.fallbackRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, { isBlocking: false, isFallback: true })
|
||||
);
|
||||
Object.keys(prerenderManifest.legacyBlockingRoutes).forEach(route =>
|
||||
onPrerenderRoute(route, { isBlocking: true, isFallback: false })
|
||||
);
|
||||
|
||||
// Dynamic pages for lazy routes should be handled by the lambda flow.
|
||||
Object.keys(prerenderManifest.lazyRoutes).forEach(lazyRoute => {
|
||||
const { dataRouteRegex, dataRoute } = prerenderManifest.lazyRoutes[
|
||||
lazyRoute
|
||||
];
|
||||
dynamicDataRoutes.push({
|
||||
// Next.js provided data route regex
|
||||
src: dataRouteRegex.replace(/^\^/, `^${appMountPrefixNoTrailingSlash}`),
|
||||
// Location of lambda in builder output
|
||||
dest: path.posix.join(entryDirectory, dataRoute),
|
||||
// We still need to use lazyRoutes if the dataRoutes field
|
||||
// isn't available for backwards compatibility
|
||||
if (!(routesManifest && routesManifest.dataRoutes)) {
|
||||
// Dynamic pages for lazy routes should be handled by the lambda flow.
|
||||
[
|
||||
...Object.entries(prerenderManifest.fallbackRoutes),
|
||||
...Object.entries(prerenderManifest.legacyBlockingRoutes),
|
||||
].forEach(([, { dataRouteRegex, dataRoute }]) => {
|
||||
dataRoutes.push({
|
||||
// Next.js provided data route regex
|
||||
src: dataRouteRegex.replace(
|
||||
/^\^/,
|
||||
`^${appMountPrefixNoTrailingSlash}`
|
||||
),
|
||||
// Location of lambda in builder output
|
||||
dest: path.posix.join(entryDirectory, dataRoute),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const nextStaticFiles = await glob(
|
||||
@@ -1025,7 +1085,8 @@ export const build = async ({
|
||||
entryDirectory,
|
||||
dynamicPages,
|
||||
false,
|
||||
routesManifest
|
||||
routesManifest,
|
||||
new Set(prerenderManifest.omittedRoutes)
|
||||
).then(arr =>
|
||||
arr.map(route => {
|
||||
route.src = route.src.replace('^', `^${dynamicPrefix}`);
|
||||
@@ -1033,6 +1094,23 @@ export const build = async ({
|
||||
})
|
||||
);
|
||||
|
||||
// We need to delete lambdas from output instead of omitting them from the
|
||||
// start since we rely on them for powering Preview Mode (read above in
|
||||
// onPrerenderRoute).
|
||||
prerenderManifest.omittedRoutes.forEach(routeKey => {
|
||||
// Get the route file as it'd be mounted in the builder output
|
||||
const routeFileNoExt = path.posix.join(
|
||||
entryDirectory,
|
||||
routeKey === '/' ? '/index' : routeKey
|
||||
);
|
||||
if (typeof lambdas[routeFileNoExt] === undefined) {
|
||||
throw new Error(
|
||||
`invariant: unknown lambda ${routeKey} (lookup: ${routeFileNoExt}) | please report this immediately`
|
||||
);
|
||||
}
|
||||
delete lambdas[routeFileNoExt];
|
||||
});
|
||||
|
||||
return {
|
||||
output: {
|
||||
...publicDirectoryFiles,
|
||||
@@ -1073,10 +1151,13 @@ export const build = async ({
|
||||
),
|
||||
// Next.js assets contain a hash or entropy in their filenames, so they
|
||||
// are guaranteed to be unique and cacheable indefinitely.
|
||||
headers: { 'cache-control': 'public,max-age=31536000,immutable' },
|
||||
headers: {
|
||||
'cache-control': `public,max-age=${MAX_AGE_ONE_YEAR},immutable`,
|
||||
},
|
||||
continue: true,
|
||||
},
|
||||
{ src: path.join('/', entryDirectory, '_next(?!/data(?:/|$))(?:/.*)?') },
|
||||
|
||||
// Next.js page lambdas, `static/` folder, reserved assets, and `public/`
|
||||
// folder
|
||||
{ handle: 'filesystem' },
|
||||
@@ -1098,7 +1179,10 @@ export const build = async ({
|
||||
...rewrites,
|
||||
// Dynamic routes
|
||||
...dynamicRoutes,
|
||||
...dynamicDataRoutes,
|
||||
|
||||
// /_next/data routes for getServerProps/getStaticProps pages
|
||||
...dataRoutes,
|
||||
|
||||
// Custom Next.js 404 page (TODO: do we want to remove this?)
|
||||
...(isLegacy
|
||||
? []
|
||||
|
||||
@@ -316,6 +316,7 @@ export type RoutesManifest = {
|
||||
regex: string;
|
||||
}[];
|
||||
version: number;
|
||||
dataRoutes?: Array<{ page: string; dataRouteRegex: string }>;
|
||||
};
|
||||
|
||||
export async function getRoutesManifest(
|
||||
@@ -353,7 +354,8 @@ export async function getDynamicRoutes(
|
||||
entryDirectory: string,
|
||||
dynamicPages: string[],
|
||||
isDev?: boolean,
|
||||
routesManifest?: RoutesManifest
|
||||
routesManifest?: RoutesManifest,
|
||||
omittedRoutes?: Set<string>
|
||||
): Promise<Source[]> {
|
||||
if (!dynamicPages.length) {
|
||||
return [];
|
||||
@@ -363,14 +365,16 @@ export async function getDynamicRoutes(
|
||||
switch (routesManifest.version) {
|
||||
case 1:
|
||||
case 2: {
|
||||
return routesManifest.dynamicRoutes.map(
|
||||
({ page, regex }: { page: string; regex: string }) => {
|
||||
return routesManifest.dynamicRoutes
|
||||
.filter(({ page }) =>
|
||||
omittedRoutes ? !omittedRoutes.has(page) : true
|
||||
)
|
||||
.map(({ page, regex }: { page: string; regex: string }) => {
|
||||
return {
|
||||
src: regex,
|
||||
dest: !isDev ? path.join('/', entryDirectory, page) : page,
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
default: {
|
||||
// update MIN_ROUTES_MANIFEST_VERSION
|
||||
@@ -616,7 +620,7 @@ export async function createLambdaFromPseudoLayers({
|
||||
export type NextPrerenderedRoutes = {
|
||||
bypassToken: string | null;
|
||||
|
||||
routes: {
|
||||
staticRoutes: {
|
||||
[route: string]: {
|
||||
initialRevalidate: number | false;
|
||||
dataRoute: string;
|
||||
@@ -624,14 +628,24 @@ export type NextPrerenderedRoutes = {
|
||||
};
|
||||
};
|
||||
|
||||
lazyRoutes: {
|
||||
legacyBlockingRoutes: {
|
||||
[route: string]: {
|
||||
fallback?: string;
|
||||
routeRegex: string;
|
||||
dataRoute: string;
|
||||
dataRouteRegex: string;
|
||||
};
|
||||
};
|
||||
|
||||
fallbackRoutes: {
|
||||
[route: string]: {
|
||||
fallback: string;
|
||||
routeRegex: string;
|
||||
dataRoute: string;
|
||||
dataRouteRegex: string;
|
||||
};
|
||||
};
|
||||
|
||||
omittedRoutes: string[];
|
||||
};
|
||||
|
||||
export async function getExportIntent(
|
||||
@@ -716,30 +730,58 @@ export async function getPrerenderManifest(
|
||||
.catch(() => false);
|
||||
|
||||
if (!hasManifest) {
|
||||
return { routes: {}, lazyRoutes: {}, bypassToken: null };
|
||||
return {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
}
|
||||
|
||||
const manifest: {
|
||||
version: 1;
|
||||
routes: {
|
||||
[key: string]: {
|
||||
initialRevalidateSeconds: number | false;
|
||||
dataRoute: string;
|
||||
srcRoute: string | null;
|
||||
};
|
||||
};
|
||||
dynamicRoutes: {
|
||||
[key: string]: {
|
||||
fallback?: string;
|
||||
routeRegex: string;
|
||||
dataRoute: string;
|
||||
dataRouteRegex: string;
|
||||
};
|
||||
};
|
||||
preview?: {
|
||||
previewModeId: string;
|
||||
};
|
||||
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
|
||||
const manifest:
|
||||
| {
|
||||
version: 1;
|
||||
routes: {
|
||||
[key: string]: {
|
||||
initialRevalidateSeconds: number | false;
|
||||
dataRoute: string;
|
||||
srcRoute: string | null;
|
||||
};
|
||||
};
|
||||
dynamicRoutes: {
|
||||
[key: string]: {
|
||||
fallback?: string;
|
||||
routeRegex: string;
|
||||
dataRoute: string;
|
||||
dataRouteRegex: string;
|
||||
};
|
||||
};
|
||||
preview?: {
|
||||
previewModeId: string;
|
||||
};
|
||||
}
|
||||
| {
|
||||
version: 2;
|
||||
routes: {
|
||||
[route: string]: {
|
||||
initialRevalidateSeconds: number | false;
|
||||
srcRoute: string | null;
|
||||
dataRoute: string;
|
||||
};
|
||||
};
|
||||
dynamicRoutes: {
|
||||
[route: string]: {
|
||||
routeRegex: string;
|
||||
fallback: string | false;
|
||||
dataRoute: string;
|
||||
dataRouteRegex: string;
|
||||
};
|
||||
};
|
||||
preview: {
|
||||
previewModeId: string;
|
||||
};
|
||||
} = JSON.parse(await fs.readFile(pathPrerenderManifest, 'utf8'));
|
||||
|
||||
switch (manifest.version) {
|
||||
case 1: {
|
||||
@@ -747,10 +789,12 @@ export async function getPrerenderManifest(
|
||||
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
|
||||
|
||||
const ret: NextPrerenderedRoutes = {
|
||||
routes: {},
|
||||
lazyRoutes: {},
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken:
|
||||
(manifest.preview && manifest.preview.previewModeId) || null,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
|
||||
routes.forEach(route => {
|
||||
@@ -759,7 +803,7 @@ export async function getPrerenderManifest(
|
||||
dataRoute,
|
||||
srcRoute,
|
||||
} = manifest.routes[route];
|
||||
ret.routes[route] = {
|
||||
ret.staticRoutes[route] = {
|
||||
initialRevalidate:
|
||||
initialRevalidateSeconds === false
|
||||
? false
|
||||
@@ -777,7 +821,68 @@ export async function getPrerenderManifest(
|
||||
dataRouteRegex,
|
||||
} = manifest.dynamicRoutes[lazyRoute];
|
||||
|
||||
ret.lazyRoutes[lazyRoute] = {
|
||||
if (fallback) {
|
||||
ret.fallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
fallback,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
};
|
||||
} else {
|
||||
ret.legacyBlockingRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
case 2: {
|
||||
const routes = Object.keys(manifest.routes);
|
||||
const lazyRoutes = Object.keys(manifest.dynamicRoutes);
|
||||
|
||||
const ret: NextPrerenderedRoutes = {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: manifest.preview.previewModeId,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
|
||||
routes.forEach(route => {
|
||||
const {
|
||||
initialRevalidateSeconds,
|
||||
dataRoute,
|
||||
srcRoute,
|
||||
} = manifest.routes[route];
|
||||
ret.staticRoutes[route] = {
|
||||
initialRevalidate:
|
||||
initialRevalidateSeconds === false
|
||||
? false
|
||||
: Math.max(1, initialRevalidateSeconds),
|
||||
dataRoute,
|
||||
srcRoute,
|
||||
};
|
||||
});
|
||||
|
||||
lazyRoutes.forEach(lazyRoute => {
|
||||
const {
|
||||
routeRegex,
|
||||
fallback,
|
||||
dataRoute,
|
||||
dataRouteRegex,
|
||||
} = manifest.dynamicRoutes[lazyRoute];
|
||||
|
||||
if (!fallback) {
|
||||
// Fallback behavior is disabled, all routes would've been provided
|
||||
// in the top-level `routes` key (`staticRoutes`).
|
||||
ret.omittedRoutes.push(lazyRoute);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.fallbackRoutes[lazyRoute] = {
|
||||
routeRegex,
|
||||
fallback,
|
||||
dataRoute,
|
||||
@@ -788,7 +893,13 @@ export async function getPrerenderManifest(
|
||||
return ret;
|
||||
}
|
||||
default: {
|
||||
return { routes: {}, lazyRoutes: {}, bypassToken: null };
|
||||
return {
|
||||
staticRoutes: {},
|
||||
legacyBlockingRoutes: {},
|
||||
fallbackRoutes: {},
|
||||
bypassToken: null,
|
||||
omittedRoutes: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
"x-now-cache": "PRERENDER"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
@@ -84,6 +84,21 @@
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1/comment-1",
|
||||
"status": 200,
|
||||
@@ -113,7 +128,7 @@
|
||||
"path": "/_next/data/testing-build-id/forever.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
"x-now-cache": "/PRERENDER|HIT/"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
"x-now-cache": "PRERENDER"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
@@ -82,6 +82,21 @@
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-4.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/HIT|STALE/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
@@ -114,7 +129,7 @@
|
||||
"path": "/_next/data/testing-build-id/forever.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
"x-now-cache": "/PRERENDER|HIT/"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "9.2.2-canary.16",
|
||||
"next": "9.2.3-canary.13",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
|
||||
5
packages/now-next/test/fixtures/21-server-props/next.config.js
vendored
Normal file
5
packages/now-next/test/fixtures/21-server-props/next.config.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
generateBuildId() {
|
||||
return 'testing-build-id';
|
||||
},
|
||||
};
|
||||
164
packages/now-next/test/fixtures/21-server-props/now.json
vendored
Normal file
164
packages/now-next/test/fixtures/21-server-props/now.json
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
{
|
||||
"version": 2,
|
||||
"builds": [{ "src": "package.json", "use": "@now/next" }],
|
||||
"probes": [
|
||||
{
|
||||
"path": "/lambda",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/forever",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/another",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/another",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/blog/post-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-1/comment-1",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-2/comment-2",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/blog/post-3/comment-3",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/lambda.json",
|
||||
"status": 404
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another2.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{ "delay": 2000 },
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/another2.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "/MISS/"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-1"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"responseHeaders": {
|
||||
"x-now-cache": "MISS"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"mustContain": "comment-1337"
|
||||
},
|
||||
{
|
||||
"path": "/_next/data/testing-build-id/blog/post-1337/comment-1337.json",
|
||||
"status": 200,
|
||||
"mustContain": "post-1337"
|
||||
}
|
||||
]
|
||||
}
|
||||
7
packages/now-next/test/fixtures/21-server-props/package.json
vendored
Normal file
7
packages/now-next/test/fixtures/21-server-props/package.json
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"next": "9.2.3-canary.13",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6"
|
||||
}
|
||||
}
|
||||
20
packages/now-next/test/fixtures/21-server-props/pages/another.js
vendored
Normal file
20
packages/now-next/test/fixtures/21-server-props/pages/another.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export async function unstable_getServerProps() {
|
||||
return {
|
||||
props: {
|
||||
world: 'world',
|
||||
time: new Date().getTime(),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default ({ world, time }) => {
|
||||
return (
|
||||
<>
|
||||
<p>hello: {world}</p>
|
||||
<span>time: {time}</span>
|
||||
</>
|
||||
);
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user