Compare commits

..

16 Commits

Author SHA1 Message Date
JJ Kasper
1f128e69e6 Publish Stable
- @now/next@2.3.18
2020-02-26 15:56:41 -06:00
JJ Kasper
f1487c92cb Publish Canary
- now@17.0.5-canary.4
 - @now/next@2.3.18-canary.0
2020-02-26 15:51:27 -06:00
JJ Kasper
45066cdf44 [now-next] Add /_next/data routes for getServerProps pages (#3771)
This adds the `/_next/data` routes for `getServerProps` pages if they exist

x-ref: https://github.com/zeit/next.js/pull/10077
x-ref: https://github.com/zeit/next.js/pull/10622
2020-02-26 21:47:51 +00:00
Ana Trajkovska
7dde9c8207 Publish Canary
- now@17.0.5-canary.3
 - now-client@7.0.1-canary.1
2020-02-26 08:00:09 +01:00
Ana Trajkovska
fd964f825d Handle deployment cancellation (#3823)
Co-authored-by: Max <8418866+rdev@users.noreply.github.com>
2020-02-26 07:21:27 +01:00
Steven
1656c9874e Publish Canary
- @now/build-utils@2.0.1-canary.0
 - now@17.0.5-canary.2
 - @now/routing-utils@1.6.1-canary.0
2020-02-25 17:32:37 -05:00
Steven
d999a3b2ad [now-routing-utils][now-build-utils] Refactor zero-config rewrites (#3832)
This PR refactors the rewrites (the dynamic routes as well as the route that prevents directory listing for zero config deployments) so they are not in the `handle: miss` phase.

This is necessary because the behavior of `handle: miss` will change in an upcoming release.

The solution is to separate these into `rewriteRoutes` that can then be merged properly with the user's routes. They will be appended to the `handle: filesystem` phase (or add the phase if it doesn't exist).
2020-02-25 22:30:36 +00:00
Joe Haddad
cfb7c9e632 Publish Stable
- @now/next@2.3.17
2020-02-25 15:19:05 -05:00
Joe Haddad
06e8472cf7 Publish Canary
- now@17.0.5-canary.1
 - @now/next@2.3.17-canary.0
 - @now/static-build@0.14.13-canary.0
2020-02-25 14:57:42 -05:00
Joe Haddad
92404135d8 [now-next] Always Emit Prerenders (#3837)
This ensures we always emit Prerender objects for bypass tokens.
2020-02-25 19:51:07 +00:00
Nathan Rajlich
8b5cc23d7c [now-cli] Remove v1 "static build" integration tests (#3833)
* [now-cli] Remove v1 "static build" integration tests

These are the last remaining v1 static type deployments being created.

* Remove from `integration.js` as well

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2020-02-24 17:19:22 -08:00
Shu Uesugi
e10b42bfdc Rename zeit.co/new → zeit.co/import (#3834)
* zeit.co/new → zeit.co/import

* Update docs URL
2020-02-25 01:35:12 +01:00
M. Heide
36f7ec4836 [examples] Fix Go build if Windows Git is configured to checkout CRLF line endings (#3821)
Fixes #3820
2020-02-24 19:53:15 +00:00
Joe Haddad
f89d1c463e Remove Backticks from URL Output (#3830)
![image](https://user-images.githubusercontent.com/616428/75176976-44434880-5703-11ea-8ca5-cb49e4a921cf.png)

![image](https://user-images.githubusercontent.com/616428/75176982-473e3900-5703-11ea-90f6-b31844a486ce.png)
2020-02-24 19:22:58 +00:00
Steven
5dc652eba9 Publish Canary
- now@17.0.5-canary.0
 - now-client@7.0.1-canary.0
2020-02-24 12:53:13 -05:00
Steven
821b2bd50b [now-client] Fix root directory with trailing slash (#3827)
There was a bug in `now-client` when deploying a directory that ends with a slash, for example `/Users/styfle/Code/myapp/` instead of the usual `/Users/styfle/Code/myapp`.

This never affected `now-cli` until we added support for defining the `rootDirectory` which allows the user to type whatever they wish in the Project Settings.

The fix is to use `path.relative()` instead of substring.
2020-02-24 17:45:10 +00:00
107 changed files with 1002 additions and 524 deletions

4
.gitattributes vendored
View File

@@ -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

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now-examples/tree/master/example-directory)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now-examples/tree/master/example-directory)
### How We Created This Example

View File

@@ -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?

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/amp)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/amp)
_Live Example: https://amp.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/angular)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/angular)
_Live Example: https://angular.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/assemble)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/assemble)
_Live Example: https://assemble.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/aurelia)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/aurelia)
_Live Example: https://aurelia.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/brunch)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/brunch)
_Live Example: https://brunch.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/charge)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/charge)
_Live Example: https://charge.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/create-react-app-functions)
[![Deploy with ZEIT Now](https://zeit.co/button)](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/_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/custom-build)
[![Deploy with ZEIT Now](https://zeit.co/button)](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_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/docusaurus)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/docusaurus)
_Live Example: https://docusaurus.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/docz)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/docz)
_Live Example: https://docz.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/eleventy)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/eleventy)
_Live Example: https://eleventy.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/ember)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/ember)
_Live Example: https://ember.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/foundation)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/foundation)
_Live Example: https://foundation.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/gatsby)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/gatsby)
_Live Example: https://gatsby.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/gridsome)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/gridsome)
_Live Example: https://gridsome.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hexo)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hexo)
_Live Example: https://hexo.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hugo)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hugo)
_Live Example: https://hugo.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/hyperapp)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/hyperapp)
_Live Example: https://hyperapp.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/ionic-react)
[![Deploy with ZEIT Now](https://zeit.co/button)](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_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/jekyll)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/jekyll)
_Live Example: https://jekyll.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/marko)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/marko)
_Live Example: https://marko.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mdx-deck)
[![Deploy with ZEIT Now](https://zeit.co/button)](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_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/metalsmith)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/metalsmith)
_Live Example: https://metalsmith.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/middleman)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/middleman)
_Live Example: https://middleman.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mithril)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/mithril)
_Live Example: https://mithril.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/mkdocs)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/mkdocs)
_Live Example: https://mkdocs.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/nextjs)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/nextjs)
_Live Example: https://nextjs.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/nuxtjs)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/nuxtjs)
_Live Example: https://nuxtjs.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/pelican)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/pelican)
_Live Example: https://pelican.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/polymer)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/polymer)
_Live Example: https://polymer.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/preact)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/preact)
_Live Example: https://preact.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/riot)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/riot)
_Live Example: https://riot.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/saber)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/saber)
_Live Example: https://saber.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/sapper)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/sapper)
_Live Example: https://sapper.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/stencil)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/stencil)
_Live Example: https://stencil.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/storybook)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/storybook)
_Live Example: https://storybook.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/svelte)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/svelte)
_Live Example: https://svelte.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/umijs)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/umijs)
_Live Example: https://umijs.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vanilla)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vanilla)
_Live Example: https://vanilla.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vue)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vue)
_Live Example: https://vue.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/vuepress)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/vuepress)
_Live Example: https://vuepress.now-examples.now.sh_

View File

@@ -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.
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/new/project?template=https://github.com/zeit/now/tree/master/examples/zola)
[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/now/tree/master/examples/zola)
_Live Example: https://zola.now-examples.now.sh_

View File

@@ -1,6 +1,6 @@
{
"name": "@now/build-utils",
"version": "2.0.0",
"version": "2.0.1-canary.0",
"license": "MIT",
"main": "./dist/index.js",
"types": "./dist/index.d.js",

View File

@@ -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,
};
}
@@ -153,6 +152,7 @@ export async function detectBuilders(
warnings,
defaultRoutes: null,
redirectRoutes: null,
rewriteRoutes: null,
};
}
@@ -224,6 +224,7 @@ export async function detectBuilders(
builders: null,
redirectRoutes: null,
defaultRoutes: null,
rewriteRoutes: null,
};
}
@@ -264,6 +265,7 @@ export async function detectBuilders(
warnings,
redirectRoutes: null,
defaultRoutes: null,
rewriteRoutes: null,
};
}
@@ -294,15 +296,13 @@ export async function detectBuilders(
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,
};
}
@@ -835,10 +835,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
? ''
@@ -891,14 +891,14 @@ function mergeRoutes(
): {
defaultRoutes: Route[];
redirectRoutes: Route[];
rewriteRoutes: Route[];
} {
const defaultRoutes: Route[] = [];
const redirectRoutes: Route[] = [];
const rewriteRoutes: Route[] = [];
if (preDefaultRoutes && preDefaultRoutes.length > 0) {
if (options.featHandleMiss) {
defaultRoutes.push({ handle: 'miss' });
const extSet = detectApiExtensions(apiBuilders);
if (extSet.size > 0) {
@@ -923,6 +923,7 @@ function mergeRoutes(
status: 308,
});
} else {
defaultRoutes.push({ handle: 'miss' });
defaultRoutes.push({
src: `^/api/(.+)${extGroup}$`,
dest: '/api/$1',
@@ -932,11 +933,11 @@ function mergeRoutes(
}
if (preDynamicRoutes) {
defaultRoutes.push(...preDynamicRoutes);
rewriteRoutes.push(...preDynamicRoutes);
}
if (preDefaultRoutes.length) {
defaultRoutes.push({
rewriteRoutes.push({
src: '^/api(/.*)?$',
status: 404,
continue: true,
@@ -969,6 +970,7 @@ function mergeRoutes(
return {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
};
}

View File

@@ -906,11 +906,11 @@ it('Test `detectRoutes`', async () => {
expect(defaultRoutes!.length).toBe(3);
expect((defaultRoutes![0] as any).src).toBe(
'^/api/date(\\/|\\/index|\\/index\\.js)?$'
'^/api/date(/|/index|/index\\.js)?$'
);
expect((defaultRoutes![0] as any).dest).toBe('/api/date/index.js');
expect((defaultRoutes![1] as any).src).toBe(
'^/api/(date\\/|date|date\\.js)$'
'^/api/(date/|date|date\\.js)$'
);
expect((defaultRoutes![1] as any).dest).toBe('/api/date.js');
}
@@ -922,13 +922,13 @@ it('Test `detectRoutes`', async () => {
expect(defaultRoutes!.length).toBe(3);
expect((defaultRoutes![0] as any).src).toBe(
'^/api/([^/]+)(\\/|\\/index|\\/index\\.js)?$'
'^/api/([^/]+)(/|/index|/index\\.js)?$'
);
expect((defaultRoutes![0] as any).dest).toBe(
'/api/[date]/index.js?date=$1'
);
expect((defaultRoutes![1] as any).src).toBe(
'^/api/(date\\/|date|date\\.js)$'
'^/api/(date/|date|date\\.js)$'
);
expect((defaultRoutes![1] as any).dest).toBe('/api/date.js');
}
@@ -970,7 +970,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
{
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -980,6 +980,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1022,7 +1024,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
{
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -1032,6 +1034,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1057,7 +1061,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
'api/[endpoint]/[id].js',
];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -1067,6 +1071,9 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1098,7 +1105,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
const files = ['public/index.html', 'api/[endpoint].js'];
const { defaultRoutes } = await detectBuilders(files, pkg, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, pkg, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -1108,6 +1115,8 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)$',
dest: '/api/[endpoint]?endpoint=$1',
@@ -1133,7 +1142,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
{
const files = ['api/date/index.js', 'api/date.js'];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -1143,6 +1152,9 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1154,7 +1166,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
{
const files = ['api/date.js', 'api/[date]/index.js'];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
expect(defaultRoutes).toStrictEqual([
@@ -1164,8 +1176,10 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)(\\/|\\/index|\\/index\\.js)?$',
src: '^/api/([^/]+)(/|/index|/index\\.js)?$',
dest: '/api/[date]/index?date=$1',
check: true,
},
@@ -1186,7 +1200,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
'api/food.ts',
'api/ts/gold.ts',
];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
featHandleMiss,
});
@@ -1197,7 +1211,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
{ status: 404, src: '^/api(/.*)?$', continue: true },
]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
@@ -1206,7 +1227,7 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
const files = ['api/user.php'];
const { defaultRoutes } = await detectBuilders(files, null, {
const { defaultRoutes, rewriteRoutes } = await detectBuilders(files, null, {
functions,
featHandleMiss,
});
@@ -1217,7 +1238,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`', async () => {
dest: '/api/$1',
check: true,
},
{ status: 404, src: '^/api(/.*)?$', continue: true },
]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
});
@@ -1239,14 +1267,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1317,14 +1345,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1350,14 +1378,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
'api/[endpoint]/[id].js',
];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1389,14 +1417,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
const files = ['public/index.html', 'api/[endpoint].js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
pkg,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)$',
dest: '/api/[endpoint]?endpoint=$1',
@@ -1420,14 +1448,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/date/index.js', 'api/date.js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1439,16 +1467,16 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
{
const files = ['api/date.js', 'api/[date]/index.js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)(\\/|\\/index)?$',
src: '^/api/([^/]+)(/|/index)?$',
dest: '/api/[date]/index?date=$1',
check: true,
},
@@ -1469,15 +1497,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
'api/food.ts',
'api/ts/gold.ts',
];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
{ status: 404, src: '^/api(/.*)?$', continue: true },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
@@ -1486,15 +1518,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`', async ()
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
const files = ['api/user.php'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
{ functions, ...options }
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { functions, ...options });
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
{ status: 404, src: '^/api(/.*)?$', continue: true },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
});
@@ -1517,14 +1553,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/user.go', 'api/team.js', 'api/package.json'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1565,14 +1601,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/[endpoint].js', 'api/[endpoint]/[id].js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1598,14 +1634,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
'api/[endpoint]/[id].js',
];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)/([^/]+)$',
dest: '/api/[endpoint]/[id]?endpoint=$1&id=$2',
@@ -1637,14 +1673,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
const files = ['public/index.html', 'api/[endpoint].js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
pkg,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, pkg, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)$',
dest: '/api/[endpoint]?endpoint=$1',
@@ -1661,14 +1697,14 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/date/index.js', 'api/date.js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
@@ -1680,16 +1716,16 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
{
const files = ['api/date.js', 'api/[date]/index.js'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
src: '^/api/([^/]+)(\\/|\\/index)?$',
src: '^/api/([^/]+)(/|/index)?$',
dest: '/api/[date]/index?date=$1',
check: true,
},
@@ -1710,15 +1746,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
'api/food.ts',
'api/ts/gold.ts',
];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
options
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, options);
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
{ status: 404, src: '^/api(/.*)?$', continue: true },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
@@ -1727,15 +1767,19 @@ it('Test `detectRoutes` with `featHandleMiss=true`, `cleanUrls=true`, `trailingS
const functions = { 'api/user.php': { runtime: 'now-php@0.0.8' } };
const files = ['api/user.php'];
const { defaultRoutes, redirectRoutes } = await detectBuilders(
files,
null,
{ functions, ...options }
);
const {
defaultRoutes,
redirectRoutes,
rewriteRoutes,
} = await detectBuilders(files, null, { functions, ...options });
testHeaders(redirectRoutes);
expect(defaultRoutes).toStrictEqual([
{ handle: 'miss' },
{ status: 404, src: '^/api(/.*)?$', continue: true },
expect(defaultRoutes).toStrictEqual([]);
expect(rewriteRoutes).toStrictEqual([
{
status: 404,
src: '^/api(/.*)?$',
continue: true,
},
]);
}
});

View File

@@ -1,6 +1,6 @@
{
"name": "now",
"version": "17.0.4",
"version": "17.0.5-canary.4",
"preferGlobal": true,
"license": "Apache-2.0",
"description": "The command-line interface for Now",

View File

@@ -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,
}
)}`
);

View File

@@ -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();

View File

@@ -133,6 +133,9 @@ export async function devRouter(
);
if (missResult.found) {
return missResult;
} else {
reqPathname = destPath;
continue;
}
} else {
if (routeConfig.status && phase === 'miss') {

View File

@@ -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;

View File

@@ -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}`;
}

View File

@@ -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 }
]
}

View File

@@ -10,14 +10,14 @@
"dest": "/blog/$1",
"check": true
},
{
"handle": "miss"
},
{
"src": "/.*",
"status": 404,
"continue": true
},
{
"handle": "miss"
},
{
"src": "/(.*)",
"dest": "/src/$1",

View File

@@ -1,8 +0,0 @@
{
"version": 2,
"routes": [
{ "handle": "miss" },
{ "src": "/pathA(?:/.+)?", "status": 404, "continue": true },
{ "src": "/pathB(?:/.+)?", "status": 404, "continue": true }
]
}

View File

@@ -1,7 +0,0 @@
{
"functions": {
"server/**/*.js": {
"runtime": "@now/node@1.2.1"
}
}
}

View File

@@ -1,3 +0,0 @@
export default (req, res) => {
res.end(`current hour: ${Math.floor(Date.now() / 10000)}`);
};

View File

@@ -0,0 +1,2 @@
module.exports = (req, res) =>
res.send(req.query.username);

View File

@@ -0,0 +1 @@
module.exports = (req, res) => res.end('42');

View File

@@ -0,0 +1,2 @@
module.exports = (req, res) =>
res.send(req.query.id);

View File

@@ -0,0 +1,3 @@
{
"rewrites": [{ "source": "/rand", "destination": "/api/fourty-two" }]
}

View File

@@ -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) => {
@@ -606,6 +584,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) => {

View File

@@ -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 }',

View File

@@ -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');

View File

@@ -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');

View File

@@ -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;
};

View File

@@ -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",

View File

@@ -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');

View File

@@ -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);

View File

@@ -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!');

View File

@@ -1,6 +1,6 @@
{
"name": "@now/next",
"version": "2.3.16",
"version": "2.3.18",
"license": "MIT",
"main": "./dist/index",
"homepage": "https://zeit.co/docs/runtimes#official-runtimes/next-js",

View File

@@ -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,35 @@ 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.lazyRoutes[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.routes[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 +492,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 +556,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 +659,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$/, '');
@@ -930,36 +963,39 @@ 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 === false
? MAX_AGE_ONE_YEAR * 10
: initialRevalidate,
lambda,
fallback: htmlFsRef,
group: prerenderGroup,
bypassToken: prerenderManifest.bypassToken,
});
prerenders[outputPathData] = new Prerender({
expiration:
initialRevalidate === false
? MAX_AGE_ONE_YEAR * 10
: initialRevalidate,
lambda,
fallback: jsonFsRef,
group: prerenderGroup,
bypassToken: prerenderManifest.bypassToken,
});
++prerenderGroup;
};
Object.keys(prerenderManifest.routes).forEach(route =>
@@ -969,18 +1005,25 @@ export const build = async ({
onPrerenderRoute(route, true)
);
// 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.keys(prerenderManifest.lazyRoutes).forEach(lazyRoute => {
const { dataRouteRegex, dataRoute } = prerenderManifest.lazyRoutes[
lazyRoute
];
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(
@@ -1073,10 +1116,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 +1144,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
? []

View File

@@ -316,6 +316,7 @@ export type RoutesManifest = {
regex: string;
}[];
version: number;
dataRoutes?: Array<{ page: string; dataRouteRegex: string }>;
};
export async function getRoutesManifest(

View File

@@ -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 },

View File

@@ -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 },

View File

@@ -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"
}

View File

@@ -0,0 +1,5 @@
module.exports = {
generateBuildId() {
return 'testing-build-id';
},
};

View 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"
}
]
}

View File

@@ -0,0 +1,7 @@
{
"dependencies": {
"next": "9.2.3-canary.13",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}

View 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>
</>
);
};

View 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>
</>
);
};

View File

@@ -0,0 +1,22 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getServerProps ({ params }) {
return {
props: {
post: params.post,
comment: params.comment,
time: new Date().getTime(),
},
};
}
export default ({ post, comment, time }) => {
return (
<>
<p>Post: {post}</p>
<p>Comment: {comment}</p>
<span>time: {time}</span>
</>
);
};

View File

@@ -0,0 +1,26 @@
import React from 'react'
// eslint-disable-next-line camelcase
export async function unstable_getServerProps ({ params }) {
if (params.post === 'post-10') {
await new Promise(resolve => {
setTimeout(() => resolve(), 1000)
})
}
return {
props: {
post: params.post,
time: (await import('perf_hooks')).performance.now()
},
}
}
export default ({ post, time }) => {
return (
<>
<p>Post: {post}</p>
<span>time: {time}</span>
</>
)
}

View 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>
</>
);
};

View File

@@ -0,0 +1 @@
export default () => 'Hi';

View File

@@ -0,0 +1,5 @@
const Page = ({ data }) => <p>{data} world</p>;
Page.getInitialProps = () => ({ data: 'hello' });
export default Page;

View File

@@ -1,6 +1,6 @@
{
"name": "@now/routing-utils",
"version": "1.6.0",
"version": "1.6.1-canary.0",
"description": "ZEIT Now routing utilities",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",

View File

@@ -0,0 +1,39 @@
import { AppendRoutesToPhaseProps } from './types';
import { isHandler } from './index';
export function appendRoutesToPhase({
routes: prevRoutes,
newRoutes,
phase,
}: AppendRoutesToPhaseProps) {
if (prevRoutes === null) {
return [];
}
if (newRoutes === null || newRoutes.length === 0) {
return prevRoutes;
}
let isInPhase = false;
let insertIndex = -1;
const routes = [...prevRoutes];
routes.forEach((r, i) => {
if (isHandler(r)) {
if (r.handle === phase) {
isInPhase = true;
} else if (isInPhase) {
insertIndex = i;
isInPhase = false;
}
}
});
if (isInPhase) {
routes.push(...newRoutes);
} else if (insertIndex > -1) {
routes.splice(insertIndex, 0, ...newRoutes);
} else {
routes.push({ handle: phase });
routes.push(...newRoutes);
}
return routes;
}

Some files were not shown because too many files have changed in this diff Show More