Giter VIP home page Giter VIP logo

sapper's Introduction

sapper

Sapper is deprecated in favor of its successor, SvelteKit, which we recommend using instead.

Financial Support

To support Sapper, SvelteKit, and the rest of the Svelte ecosystem, please consider contributing via OpenCollective.

License

MIT

sapper's People

Contributors

akihikodaki avatar antony avatar artemjackson avatar benmccann avatar conduitry avatar cudr avatar dependabot[bot] avatar dummdidumm avatar ehrencrona avatar elcobvg avatar emiltholin avatar fledgling-vish avatar freedmand avatar habibrosyad avatar jayphen avatar kevmodrome avatar lukeed avatar mrkishi avatar nikku avatar nolanlawson avatar nsivertsen avatar pgjones avatar pngwn avatar rich-harris avatar s3ththompson avatar samccone avatar sanderhahn avatar teoxoy avatar thgh avatar zigomir avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sapper's Issues

Router API

Please provide Router API for defining routes with code. I personally don't like directory structure based routing. NuxtJs stated with directory based routing but now, NuxtJs also provides a Router API for defining routes.

`<noscript><img src=...` in Svelte template loads image anyways

Not sure if this is a Sapper-specific or a general Svelte issue. I have a Svelte template I call "LazyImage" that loads a detailed image asynchronously while presenting a low-res fallback initially. In case the user doesn't have JavaScript, I want to present the detailed image first. Within my template I have:

<noscript>
  <img src="...">
</noscript>

But when I run the Sapper site and navigate to the home page with JS enabled, the Network panel of Chrome dev tools shows the <noscript> images as loading. If I comment out the <noscript> part of my template, the image does not load (I'm sure of this because I've tried it with distinct images that are not loaded from the JS version). The <noscript> behavior works fine when JS is disabled.

I know Svelte compiles to JS, but since it's being server-side rendered, I'm curious if there is a good reason why the network is requesting the <noscript> version (maybe I'm missing something with my service worker or caching?). Any insights would be appreciated, and if this issue is specific to Svelte I'm happy to reopen there.

Remove async/await

Currently, Sapper requires Node 8, which means you can't run it on AWS Lambda and what-have-you

Error if routes clash

It should be impossible to have [foo].html next to [bar].html for obvious reasons — should be a compile time error

only serve hydrate code for initial route

After Sapper hydrates the initial route, navigating to other routes causes the page to be destroyed and recreated from scratch. It's therefore not necessary for the hydration code to be sent to the browser other than for the initial route.

Not exactly sure how to achieve that, but it would be a win.

Minify HTML templates

Probably isn't worth doing this on each page render, but the initial templates could be minified to save a few bytes

Don't re-render documents whose contents can't change

This page always returns the same markup. If it were possible to determine that statically, we could render the page once and serve it from a cache thereafter.

Gets a little tricky though — even that page has a dynamic-looking expression within the nav (that determines which nav link is highlighted). Would need some form of whole-app analysis. As such, it's probably not something we can do any time soon.

Page routes, server routes and status codes

We're currently missing a sensible way to manipulate non-standard page route responses: not founds, redirects and so on.

A /blog/[slug].html has no way to return a 404 or 301 depending on the slug -- you'd have to handle it client-side upon initialization.

I'm just getting started with sapper, but here are some ideas that might or not work:

  • Server routes could be able to render page routes

    /blog/[slug].js could then either perform something non-standard or render a /blog/_[slug].html page route.

  • Server routes could take precedence over page routes

    Currently, you can't have both /blog/[slug].js and /blog/[slug].html. If that was allowed, the server route could have first shot at serving the url, defaulting to the page route otherwise. This would be a more organized version of handling certain urls with express above sapper middleware. Not exactly pretty.

  • preload could have knowledge about response codes

    Instead of only returning data, preload() could optionally expect more info about the response, eg. { data: {}, status: 301, redirect: '/bleh' }. This would be handled automatically by sapper both at the server ("SSRing" redirects and 404s) and the client (automatically triggering routes).

    I don't know if that's giving preload too much power, but I think it's worth exploring things in that direction. If not preload, a similar feature.

    It'd be nice to handle auth this way, too (imagine RealWorld's settings page redirecting to login by simply changing preload a bit, without client/server differences).

Thoughts?

Interactive stack traces

In dev mode, it'd be nice if the stack trace contained links that took you to the lines in question. (In prod mode maybe we don't want to show the stack trace?)

Service worker 'side rendering'

I hadn't encountered this phrase before, but @dfabulich has an interesting suggestion — the service worker could perform 'SSR' if it had the necessary code to hand.

Not quite sure how practical that is (we'd basically need to load and run the entire server webpack bundle in the service worker, which probably means generating a separate productionised version that doesn't assume any Nodeisms), but it could be a performance win? Am not quite sure, need to think through all the ramifications.

Render `main.js` to same directory, so it can use relative imports

At present, main.js is written to the destination directory (usually .sapper). That was so that we could write it to /tmp in Now, back before building was separated out from serving.

Writing it back to the same folder (as .main.rendered.js or something) would allow it to use relative imports, when necessary.

Might then be a bit weird that you can't do that with service-worker.js. Need to think about that, maybe in a separate issue.

Nested routes

It would be helpful if routes/settings/[submenu].html matched both /settings and /settings/blah — in the first case, params.submenu would be null, and in the second case it would be "blah".

If there was a routes/settings.html or routes/settings/index.html, it should take precedence.

Separate build from server

At present the middleware is responsible for running the webpack build, even in prod mode. That's convenient, but suboptimal in cases where you don't want to run the build on the server (e.g. lambda)

Hooks

Saying you wanted to show a loading indicator when navigating between routes, or something of that nature — the best way to do that would be to have a navigation hook:

import { onnavigate } from 'svelte/runtime/app';

onnavigate((from, to, promise) => {
  console.log(`navigating from ${from.href} to ${to.href}`);
  const loading = new LoadingIndicator();
  promise.then(loading.destroy);
});

Need to consider what the arguments should be. Is there a possibility of something like onprogress, for example? Should from and to just be hrefs, or should we also get params etc? Should it be possible to cancel the navigation, or change it, or inject some data (e.g. {slidingTo: 'left'}), or delay it pending some operation?

And should it be onnavigate(...), or on('navigate', ...)? i.e. do we anticipate adding more events?

Webpack help

Hi - I've been using basic Express and Koa for some time and missed the boat on a few generations of Node tech (particularly Webpack). Trying to catch up with this and/or Svelte framework.

When I run node server.js I am expected to have made a webpack.client.config.js and webpack.server.config.js already. I see some sample JSON configs for these in other repos (such as https://github.com/sveltejs/template-webpack ). What's the right way to set these up so that I am webpack-ing all the files of a sapper app?

Testing

There should be a really good way to write acceptance tests for a Sapper app, maybe cleanly integrating with services like Cypress.

Support JSX

Would it be possible to provide a mechanism for writing templates in JSX rather than svelte? I guess it would be a welcome addition and could potentially address the barrier to entry for people coming from a react background.

Detect static routes and avoid re-render

In a lot of cases (e.g. this about page), there's no need to hydrate the page because nothing is interactive. We can just wait for the first navigation event.

This is perhaps something that belongs in Component.render(...):

const { html, head, css, interactive } = Component.render(data);

// if `interactive === false`, set `window.SAPPER_IS_INTERACTIVE = false`,
// then we don't bother with the initial `navigate(new URL(window.location))`

Support e.g. Hapi

Currently Sapper assumes you're using Express (though it may also work with Connect? Haven't tried). Would be interesting to see how straightforward it'd be to support Hapi and others as well

Support DELETE requests

I imagine (though I'm not sure) that Sapper supports all of the request types that express supports, but trying to export a DELETE handler currently won't work because delete is a reserved keyword, so export function delete(){} won't work.

Is there a clever workaround to trick js into letting me use delete? If not, could we add one to Sapper?

I thought maybe webpack harmony magic would let this work, but it doesn't seem to:

export default {
	delete(req, res) {
		console.log('delete');
	}
};

Thanks! And great work as always, Sapper is fun.

Equivalent of onload for Sapper-loaded pages

Is there an easy event handler for when Sapper navigates to and loads a page?

For my particular use case, I'm lazy loading images and swapping a blurry image src with a more detailed image src after the document has loaded. This works great using window.onload when I initially navigate to the page or hard refresh, but when navigating from another page within my Sapper app, the onload method is never called. Is there a Sapper equivalent for onload?

Support for static site generation

@Rich-Harris mentioned in a Hacker News thread that Sapper will eventually have static site export functionality. I've created this issue to track the progress on that and potentially see if there's anything that can be done to jump the gun.

(For my specific use case, I really want to start using Sapper to build progressive static websites that I can deploy with Netlify)

Service worker

Ideally, the user would be able to write a custom service worker (much as you have to bring your own server), but it would be straightforward to generate a cache manifest with all the webpack-generated stuff, static routes, assets, etc.

Link preload

When serving pages, we know ahead of time the URL of the main.[hash].js file that needs to go with it — it would be easy to add a preload header.

We could probably figure out what other things need to be sent by inspecting the generated HTML (<link rel=stylesheet>, <img> etc). Maybe there's an existing module that does that?

More ambitiously we could attempt H2 push, but I'm not sure what's involved there.

Store preloaded data

If an <a> element has rel=prefetch, Sapper should store the results of preload for the duration of the interaction rather than calling it again following click, since there's no reason to believe the data will be coming from the service worker cache the second time round.

Stream document up until first dynamic content

We don't need to wait for preload to resolve before serving the beginning of the document (up to the first %sapper.whatever% tag whose value isn't already known). Doesn't win us much, but still probably worth doing.

Export static site

For static sites (e.g. svelte.technology), it might be nice to have an equivalent of next export. Could be done like so:

// scripts/export.js
const exporter = require('sapper/export');

const pages = [
  '/',
  '/guide',
  '/repl',
  '/blog'
].concat(getListOfBlogPostsSomehow());

exporter.export(pages, 'dist').then(() => {
  console.log('done');
});

That would run server.js in a separate process and basically just curl those URLs into dist, and copy over the assets folder and the files generated by the compiler.

Single npm package with a single config file

NuxtJs is a single package/Cli/Express middleware and it hides all other dependent packages like webpack etc. NuxtJS has an optional single config file (nuxt.config.js) for setting user defined options. Sapper should do the same.

sensible approach to logging

Sapper shouldn't try to do the job of dedicated logging middleware, but it should provide some visibility into what's happening. Not sure what established practices are here, probably worth cribbing from Next and Nuxt

Inline main.js

It's small enough that maybe it doesn't make sense to make an extra request?

Programmatic navigation

At some point we'll need to be able to do this sort of thing:

import { goto } from 'sapper/runtime/app.js';

goto('/a?b=c').then(() => {
  // navigation succeeded
});

goto('/d', { replaceState: true }).then(...)

Presumably it would only fail if the href matched some route and there was an error during preload or render.

Open question whether or not it should navigate if no route is matched (i.e. just doing window.location.href = href). I suppose probably yes.

Send preloaded data to client

Rather than the initial page doing preload on both server and client, the server should send the preloaded data with the client app, so that it's unnecessary.

Process service-worker.js with webpack?

Follow-up to #40. Does it make sense to try and run webpack on service-worker.js?

It's a little awkward to do so, since the service worker needs to be rendered after the client bundle has been created (as it depends on the assets generated therein). And it would be a shame to add another webpack config. It would also be a shame to include all the unnecessary gubbins webpack would add to the file.

The alternative is to stick with the process we have now, which (at least post-#40) might be a little confusing, since it means main.js and service-worker.js are subject to different rules.

Windows support

Looks like Sapper doesn't work on Windows yet...

C:\Apps\Testarea\svelte\_sapper>npm run dev

> [email protected] dev C:\Apps\Testarea\svelte\_sapper
> node server.js

fs.js:1214
  binding.utimes(pathModule._makeLong(path), atime, mtime);
          ^
Error: EINVAL: invalid argument, utime 'C:\Apps\Testarea\svelte\_sapper\.sapper\main.js'
    at Object.fs.utimesSync (fs.js:1214:11)
    at create_client_main (C:\Apps\Testarea\svelte\_sapper\node_modules\sapper\lib\utils\create_app.js:33:6)
    at create_app (C:\Apps\Testarea\svelte\_sapper\node_modules\sapper\lib\utils\create_app.js:54:2)
    at connect (C:\Apps\Testarea\svelte\_sapper\node_modules\sapper\lib\index.js:22:2)
    at Object.<anonymous> (C:\Apps\Testarea\svelte\_sapper\server.js:20:9)
    at Module._compile (module.js:635:30)
    at Object.Module._extensions..js (module.js:646:10)
    at Module.load (module.js:554:32)
    at tryModuleLoad (module.js:497:12)
    at Function.Module._load (module.js:489:3)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] dev: `node server.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] dev script.
npm ERR! This is probably not a problem with npm. There is likely additional log ging output above.
npm ERR! A complete log of this run can be found in:
npm ERR!     C:\bin\npm-cache\_logs\2017-12-17T21_11_38_903Z-debug.log

dev server sometimes requires restart after editing route.html files

Moved from sveltejs/sapper-template#14 cc @1wheel


I'll get an error like this on the client:

process-update.js:136 [HMR] Update check failed: Error: Manifest request to /client/7f71269cd30032b87e4f.hot-update.json timed out.
    at XMLHttpRequest.request.onreadystatechange (http://localhost:3000/client/main.7f71269cd30032b87e4f.js:64:22)
handleError @ process-update.js:136
cb @ process-update.js:47
Promise rejected (async)
check @ process-update.js:84
module.exports @ process-update.js:42
processMessage @ client.js:251
handleMessage @ client.js:131
handleMessage @ client.js:94
bootstrap 7f71269cd30032b87e4f:63 Uncaught (in promise) Error: Manifest request to /client/7f71269cd30032b87e4f.hot-update.json timed out.
    at XMLHttpRequest.request.onreadystatechange (bootstrap 7f71269cd30032b87e4f:63)
request.onreadystatechange @ bootstrap 7f71269cd30032b87e4f:63
Promise rejected (async)
check @ process-update.js:81
module.exports @ process-update.js:42
processMessage @ client.js:251
handleMessage @ client.js:131
handleMessage @ client.js:94

And then everything hangs. API routes don't start processing requests (no console.log printing in the terminal) until the process is killed and then requests finish.

Don't know enough about this stack of tools to debug, but might have something to do with lack of error handling here?

preload({ params, query }) {
  return fetch(`/api/feed`).then(r => r.json()).then(posts => {
    return {posts} 
  })
}

Prioritise prefetching

At present, Sapper prefetches all code-split chunks in no particular order. It could do better. In increasing order of difficulty:

  • Allow prioritisation via some sort of config
  • Prioritise based on presence of links on page
  • Prioritise based on prominence of links (e.g. get the big hero link first, links in footer below the fold last)
  • Prioritise based on how people actually interact with the app

Also, in some cases it'd make sense not to prefetch at all.

Store can leak between pages

A (unlikely but possible) security issue — if a page sets a value on store, it will be present when that page (or any other page also using the store) is re-rendered for another request. In extreme cases this could result in personal information being shared.

Not totally sure what the best solution is.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.