Sapper: Example Serverless Arquitecture on Now v2

Created on 15 Feb 2019  ·  57Comments  ·  Source: sveltejs/sapper

It seems that Now (zeit.co/now) is moving towards a serverless approach.
Is there an example of Sapper working with Now v2?

Thanks

Most helpful comment

Hey everyone, we've just optimized Sapper for Now when using sapper export, this allows you to deploy from the boilerplate with now by using "build": "sapper export" - nothing else is required! We've also added an example showing this as well.

All 57 comments

I have no idea what I was doing and it was not successful:

now.json

{
  "version": 2,
  "builds": [
    { "src": "index.js", "use": "@now/node-server" }
  ]
}

index.js

require('./__sapper__/build/index.js')

demo: https://sapper-template-114-izlvje2aa.now.sh shows 500 error
Log:

Error while initializing entrypoint: { Error: ENOENT: no such file or directory, scandir '/var/task/user/static'
    at Object.fs.readdirSync (fs.js:904:18)
    at walk (/var/task/user/index.js:4430:20)
    at module.exports.993.module.exports (/var/task/user/index.js:4496:3)
    at module.exports.432.module.exports (/var/task/user/index.js:1654:2)
    at Module.<anonymous> (/var/task/user/index.js:3297:56801)
    at e (/var/task/user/index.js:3276:124)
    at /var/task/user/index.js:3276:923
    at Object.824 (/var/task/user/index.js:3276:933)
    at __webpack_require__ (/var/task/user/index.js:22:30)
    at Object.138 (/var/task/user/index.js:309:1)
  errno: -2,
  code: 'ENOENT',
  syscall: 'scandir',
  path: '/var/task/user/static' }

After removing sirv(static)

Error while initializing entrypoint: { Error: ENOENT: no such file or directory, open '__sapper__/build/build.json'
    at Object.fs.openSync (fs.js:646:18)
    at fs.readFileSync (fs.js:551:33)
    at Rt (/var/task/user/index.js:4086:20874)
    at /var/task/user/index.js:4086:57860
    at Module.<anonymous> (/var/task/user/index.js:4086:57968)
    at e (/var/task/user/index.js:4065:124)
    at /var/task/user/index.js:4065:923
    at Object.921 (/var/task/user/index.js:4065:933)
    at __webpack_require__ (/var/task/user/index.js:22:30)
    at Object.602 (/var/task/user/index.js:2642:1)
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: '__sapper__/build/build.json' }

I tried several to make a custom builder (now-sapper) but without success...

Any progress on this?

@vladejs you can rest easy knowing that all the Sapper/Svelte sites, docs, examples are all hosted on now v1. Dogfooding is key :)

There hasn't been any progress on this that I know of, but I'm pretty sure it will be a focus after Svelte 3 is out the door.

One unfortunate thing that makes this a bit more pressing is that Now apparently isn't allowing v1 for new projects, only for ones created before a certain date. I'm not sure why they decided to have the window be so narrow between the introduction of v2 and disallowing v1 on new projects. I'm pretty sure I read when v2 was announced that "don't worry, v1 isn't going anywhere anytime soon", but I certainly did not get the impression that it was going to be disallowed for new projects so quickly.

Progress: https://sapper-template-now-p0lz941iy.now.sh/

  • custom builder (now-sapper)
  • build locally so no npm scripts on now
  • no external rollup libs so no npm install on now
  • express
  • module.exports in server.js based on env
  • refresh on /blog is broken

@Conduitry As far as I know, users with projects on v1 can create new v1 projects. Only users that never used v1 are forced to use v2.

This is awesome news, well done @thgh

Do you reckon you'll be able to get it running with Polka?

What is the likelihood of a v2 app working with this? I've got a mountain of stuff to migrate and I'm not sure I'm ready just yet!

New version: code / result

  • only required files included
  • fixed /blog (process.env.PORT was undefined)

edited for clarity

You can try v2 yourself, I think it should work.

@lukeed Polka says:

module initialization error: TypeError
    at _addListener (events.js:239:11)
    at Server.addListener (events.js:297:10)
    at new Server (_http_server.js:269:10)
    at Object.<anonymous> (/var/task/launcher.js:30:16)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)

Does now-sapper exist anywhere besides in the package published to npm? https://www.npmjs.com/package/now-sapper doesn't have any readme yet or repo links or anything.

Now it exists: https://github.com/thgh/now-sapper

@antony got Polka working, had to export the app.handler instead.

How about putting the example app itself somewhere open? I'd rather not form a relationship with a "zeit" (which might be amazing...) to take a look. Currently clicking on the link about ending in _src requires some kind of account or login.

@kylecordes without login: code / result

@thgh looks great! Yeah - Polka doesn't export the handler directly like express. Awesome work!

@kylecordes I think you can also still set a project to open source which will allow anonymous access to _src but github is fine too :)

Can this added to sapper with a stage script in package.json ?

It's nice we have an example.

I'm also interested if we can take this a bit further. If I understand serverless correctly, the whole point is to do code splitting on serverside as well.

This section from next.js explains well how they handle serverless build.

The serverless target will output a single lambda per page. This file is completely standalone and doesn't require any dependencies to run

Would sapper consider supporting a build like this? Or is it even viable? I think it would be really great, as serverless benefits are numerous.

Yeah, to be on par with the Next.js builder it would need to create a lambda for every route

Hi, im building a "sapper+bulma crud"

my now v2 implementation is here: diff demo

Do the examples I see here inherently support server routes, or no?

@horizonshadow yes, e.g. sapper-template has a server route for blog posts.

Was playing around with this just using the @now/node builder, and I'm pretty sure once https://github.com/zeit/ncc/issues/216 gets to now-builders, it'll "just work".

So you'd set the now-build script in package.json to sapper build, and then set @now/node to __sapper__/build/index.js.

I think, anway.

@HorizonShadow While, I think that it will be great when @now/node to work out of the box... this is still a monolithic build. A @svelte/sapper builder that splits each route into it's own lambda function like @now/next does would be needed to take full advantage of the Now V2 architecture.

Hi,

Base on @danielschmitz modifications, I created a sample repo sapper-now-template base on the original sapper-template (diff).

I don't know if it would make sense to make a Pull Request on the original sapper-template repo based on these modifications, or if you want to keep the template agnostic from Now (Though I was personnaly surprised to see it recommended on the documentation, but not working directly)

Thank you very much anyway for your great work ! Tell me if I can be of any help :)

@vfabing The official template already has explicit netlify support, so I would imagine that adding now v2 support would be welcome also.

For a lot of people, myself included, this is a huge problem right now.

I managed somehow to deploy to now 2, based on StackOverflow
Not too sure about the service worker, not that i need it right now, but it got the application deployed

now.json
json{ "name": "portfolio", "version": 2, "builds": [ { "src": "__sapper__/build/index.js", "use": "@now/node-server", "config": { "includeFiles": [ "build.json", "../../package.json", "../build/**", "../../static/**", "../../node_modules/**" ], "maxLambdaSize": "15mb" } }, { "src": "static/**", "use": "@now/static" }, { "src": "__sapper__/build/client/**", "use": "@now/static" } ], "routes": [ { "src": "/(.*(\\.css)|(\\.json)|(\\.png))", "dest": "/static/$1" }, { "src": "/client/(.*)", "dest": "/__sapper__/build/client/$1" }, { "src": "/(.*)", "dest": "/__sapper__/build/index.js" } ] }

@kevin-DL I'm continuing to research this issue and have observed the following:

  • When using Rollup, you can deploy everything to Now v2, including the service worker, if you copy package.json to the __sapper__/build directory AND use now-sapper builder. This is documented here and Zeit have sorta promised to have a fix within the following weeks:

https://spectrum.chat/zeit/general/now-cli-deployment-doesnt-build-package-json-dependencies~34dac90d-46fe-499a-89bc-58bffe50a9ab

  • When using Webpack (as I have just switched in my project), this trick doesn't work and nothing I tried is able to deploy dependencies correctly. I'm going to try other stuff tonight, including your now.json file.

The most worrying thing for me is the fact that Sapper apparently needs to connect to its own JSON API locally to perform state hydration, and that's not possible when using AWS Lambdas (which are under the hood of Zeit v2, to my understanding), as documented here: https://spectrum.chat/zeit/general/is-it-possible-to-self-connect-to-127-0-0-1-from-within-lambda~8dca04eb-99fb-49ad-a8be-de1c21335396

Whatever black magic now-sapper does to make it possible, I don't know and would love any and all input on this (I'm also including rollup-plugin-json in the Rollup build variant in addition to the standard Sapper config, FWIW).

Also worth mentioning that I've switched to webpack because Rollup keeps screwing with require dependencies in third party libs like Auth0 but that's probably a completely different issue.

I am a bit confused with @kevin-DL 's now.json suggestion as it has a seperate route for client. Isn't the client on the same layer as the server stuff??

@kaleidawave As far as i understand, the routes are just a mapping of where to go depending on the incoming request. When you build the application, you get a client and a server folders so it made sense to me to split it like that.
I stopped at the first config that worked for me there is probably a way to optimise it.

@vfabing 's solution works for me. Thanks for the easy setup!

However, perhaps it's the use of webpack but the main.js is ~60kb. This is pretty egregious when you consider the sapper realworld app is like ~5kb for the home page.

Edit:
I switched over to the rollup config from the sapper template. Now the bundle size is ~12kb. Still much larger than the RealWorld sapper app for some reason.

Edit 2:
I am building first locally then deploying. Realized then that Sapper was building in dev mode. Now that I've set NODE_ENV to "production", it's building within the ~5-8kb range now.

Here's a deployed link on https://sapper-now-template.now.sh/

I've not read this thread and I don't use now. Do we need to put together a custom loader or something? Is there something someone has built that works without any issues? Or maybe we just need to recommend a different host if now v2 is just causing too many problems?

I'm just trying to work out if there is something we need to do as regards this issue or if it is just a support thing.

I believe sapper should be now v2 aware, since the project is inspired by
Next.js which has excellent support for it.

On Fri, Jul 26, 2019, 6:45 PM pngwn notifications@github.com wrote:

I've not read this thread and I don't use now. Do we need to put together
a custom loader or something? Is there something someone has built that
works without any issues? Or maybe we just need to recommend a different
host if now v2 is just causing too many problems?

I'm just trying to work out if there is something we need to do as regards
this issue or if it is just a support thing.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/sveltejs/sapper/issues/564?email_source=notifications&email_token=ADANIARCGSKDDV2YU63UMMDQBN5APA5CNFSM4GXXXMTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD254ATI#issuecomment-515620941,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADANIARGVGIU4537MI46HATQBN5APANCNFSM4GXXXMTA
.

next.js has excellent support because it is built by the now team, Sapper was inspired by next but I don't see why that should mean we need to align with a specific, proprietary architecture. Quite frankly, given recent experiences, it's hard to even recommend them.

now v2's requirement are very specific and no other host that I'm aware of has the same requirements. We might be able to provide some guidance or even a separate package to help smooth out these issues but I don't see any reason why Sapper would have first class support for now out of the box since their shift to serverless in v2.

@vladejs That's not correct. My understanding is that Sapper can export static sites for some projects, which will work great on Now v2, but more complex Sapper apps that require the server will not be optimized for Now v2 (they will work, but only slowly, as the server would need to start up again for each request).

mmm. Interested to know how Next do it, since most basics apps made with
Next.js also requires a server.

Also, Zeit provides guides on how to make an Express server serverless,
which is done by just using Express as middleware and discarding routing.
Routing is handled by now.

I also saw a comment from a Zeit team member on one of their repos saying
that sapper should work great on serverless environments.

Not going in technical details but it should be possible to decompose the
routes on independent lambdas as Next.js does when setting it's serverless
config to true, at the end, both uses the filesystem as routing.

Also, Zeit has improved it's serverless functions by natively using common Express functions on the request and response objects:

https://zeit.co/blog/now-node-helpers

next.js has excellent support because it is built by the now team, Sapper _was_ inspired by next but I don't see why that should mean we need to align with a specific, proprietary architecture. Quite frankly, given recent experiences, it's hard to even recommend them.

@pngwn , there is some discussion about bringing sapper to now v2 here:
https://github.com/zeit/now-examples/issues/193

Hey everyone, we've just optimized Sapper for Now when using sapper export, this allows you to deploy from the boilerplate with now by using "build": "sapper export" - nothing else is required! We've also added an example showing this as well.

Is possible with that solution export authenticated apps?

The rules about when you can export still apply - https://sapper.svelte.dev/docs#When_not_to_export

Being able to serve completely static sites on Now isn't anything new, and nothing about this seems particularly specific to Sapper.

Okay, it's great for the config to be simplified :+1: But this doesn't address serverless at all.

Exactly

On Fri, Aug 2, 2019, 1:32 AM Nathaniel Hill notifications@github.com
wrote:

Okay, it's great for the config to be simplified 👍 But this doesn't
address serverless at all.


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/sveltejs/sapper/issues/564?email_source=notifications&email_token=ADANIAXSED4E4GENDWUMMVLQCPBFVA5CNFSM4GXXXMTKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3MUQZI#issuecomment-517556325,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADANIASVJDLWMWGJ4LHEQNLQCPBFVANCNFSM4GXXXMTA
.

Not sure if I'm late with this but looks like you could put your authentication functions into an /api folder as described here to automatically deploy as serverless functions

@aurnik it's more about a function-per-route like Next does.

The rules about when you can export still apply - https://sapper.svelte.dev/docs#When_not_to_export

Being able to serve completely static sites on Now isn't anything new, and nothing about this seems particularly specific to Sapper.

While this used to be true for next.js, it's no longer the case after the release of next.js 9. A next.js application can now be static and dynamic at the same time

_Now_ is tackling the serious cold start problem with lambdas, by simply lowering the lambda cold boot time to an acceptable level (100-300 ms) through server side code splitting and tiny bundles. (Instead of one large monolithic bundle, that takes up to 2 sec to load into memory).

This is a huge advantage for people who want to go the serverless route, and a large plus for Nextjs on the Next-vs-Sapper-comparison-sheet that one might draw mentally, when about to embark on a new project.

As @rauchg has pointed out, the Sapper architecture, inspired by Next's, seems to be perfectly usable for serverless code splitting.

It'd be a pity, if we wouldn't see a marriage between now and sapper - as sapper is still simply leaner and more efficient than react - and it's hard to forego efficiency. But Next+Now enabling killer-features like serverless prerendering makes Next even more appealing, in my opinion, as long as Sapper did not follow suit.

Surely it is possible to achieve at least a meaningful portion of this kind of architectural improvement / code split speed booth without becoming bound to one specific serverless platform/vendor? Because while I'm sure Now is a wonderful wonderful thing… It is not reasonable to expect that one product/vendor to become "the" way to host efficiently.

@kylecordes nobody is suggesting that, what is being suggested is a solution for all serverless-function based platforms. Now is a good starting place as it allows you to host on AWS, GCP, and possibly Azure in the near future.

Being able to make a Sapper project split a project into functions based upon routes would be a step forward in this direction.

Yes. If I get any spare time this month I'll give it a go. I'll make a fork called sapperless to experiment with building route-based functions and maybe it could be folded back into sapper at some point.

I've created a sort-of evolution of the previous now-sapper builder by @thgh .

You can test it out here: https://github.com/beyonk-adventures/now-sapper - by simply sticking the github URL into your now.json.

Feedback is welcome.

The roadmap (which I certainly need help with) is:

  • Serve static assets without sirv by exposing them as static routes.
  • Route splitting (this is the big one)

@antony Static assets are now served as static routes. Thanks to your refactor!

@thgh Amazing! That's the next roadmap item checked off. Now we just see what @NathanielHill can come up with :dancer:

@antony Unfortunately, I'm not going to have time for this any time soon.

@NathanielHill Ah that's a shame.

Anyone that has got a working copy of now-sapper-demo running on Zeit Now v2?

I have SSR issues with the /blog part: https://github.com/beyonk-adventures/now-sapper-demo/issues/5

@antony Any tips? Thanks!

@tomsoderlund It works without issue:

 ant@void  ~/Projects/now-sapper-demo   master  now
> UPDATE AVAILABLE Run `npm i -g now@latest` to install Now CLI 17.0.3
> Changelog: https://github.com/zeit/now/releases/tag/[email protected]
> Deploying ~/Projects/now-sapper-demo under dsrbl
> Using project test-v2-qa
> NOTE: To deploy to production (test-v2-qa-ten-flame.now.sh), run `now --prod`
> https://test-v2-qa-fvkozm8hw.now.sh [1s]
> Ready! Deployed to https://test-v2-qa.xxx.now.sh [in clipboard] [15s]

https://test-v2-qa-fvkozm8hw.now.sh

closing this issue as I am happy with the way that Sapper works on now v2, and I think route splitting should be addressed in a separate issue.

@antony Yes, thanks - I tried it last night too and it worked great!

(here was the fix https://github.com/beyonk-adventures/now-sapper-demo/issues/5#issuecomment-583854519)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Rich-Harris picture Rich-Harris  ·  3Comments

Rich-Harris picture Rich-Harris  ·  3Comments

nolanlawson picture nolanlawson  ·  4Comments

Rich-Harris picture Rich-Harris  ·  4Comments

freedmand picture freedmand  ·  4Comments