Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next export (static builds) #604

Closed
rauchg opened this issue Jan 1, 2017 · 30 comments
Closed

next export (static builds) #604

rauchg opened this issue Jan 1, 2017 · 30 comments

Comments

@rauchg
Copy link
Member

rauchg commented Jan 1, 2017

This might be built in (if it's not too opinionated), or a separate "core module" (if it has too many "options").

The idea is that one will be able to run next export and yield a build directory that doesn't require a server.

  • next export -o customDir should be possible
  • Each page can optionally precompute getInitialProps to have pre-rendered data when it's first loaded
  • The export config could live in next.config.js (export object)
@arunoda
Copy link
Contributor

arunoda commented Jan 1, 2017

How about if we ignore getInitialProps for the static build.
We simply ignore that.

Is that something we could consider?

@rauchg
Copy link
Member Author

rauchg commented Jan 1, 2017

Definitely. Client-only getInitialProps is a possibility.

@yn5
Copy link

yn5 commented Jan 9, 2017

@rauchg @arunoda Wouldn't ignoring getInitialProps defeat the purpose of a static site? There would still be a need for a server to get those initial props right? Or did I maybe miss something in the previous discussion?

@rauchg
Copy link
Member Author

rauchg commented Jan 9, 2017

There are two forms of static sites. The one where the data is 100% static, and the one where it's not. And there's a hybrid where you ship props pre-computed with each page and data can still be fetched dynamically

@yn5
Copy link

yn5 commented Jan 11, 2017

@rauchg React inherently allows the hybrid form trough its componendDidMount hook. I'd love to see the next export feature to generate a truly static site, otherwise I'll have to open another feature request once it is finished ;)

@balupton
Copy link

balupton commented Jan 15, 2017

There are two forms of static sites. The one where the data is 100% static, and the one where it's not. And there's a hybrid where you ship props pre-computed with each page and data can still be fetched dynamically

What type of static site is this command planning on exporting?

Let's perhaps define them these ways:

  • static sites that don't require client-side rendering (they can work without javascript)
  • static sites where certain pages or abilities require client-side rendering (needing some javascript)
  • static sites where each page is then assisted by client-side rendering (requiring some javascript) - e.g. single page web apps

@balupton
Copy link

balupton commented Jan 15, 2017

Also, what exactly is the benefit of zeit:next exporting a static site?

From my understanding, zeit:now will still wrap static sites in a node.js app (zeit:serve) - and zeit:now even trumps most static deployment options anyway.

@bguiz
Copy link

bguiz commented Jan 21, 2017

Also, what exactly is the benefit of zeit:next exporting a static site?

@balupton Allows one to host on github pages, aws s3, etc.

@bguiz
Copy link

bguiz commented Jan 21, 2017

As an alternative, I tried to get the static content using wget. Although it works with other of my projects (without using next), it does not work well here with next.

@jferrettiboke @stretchkennedy Where internal links are unknown at "build time", I think the approach used by static-site-generator-webpack-plugin where you simply list all of the URLs it needs to render in one place, works quite well.

Of course you don't want to be doing this by hand - I have a script that does this based on matching file names within a directory: find-posts

( Continuing conversation here from #604 )

@balupton
Copy link

balupton commented Jan 30, 2017

@balupton Allows one to host on github pages, aws s3, etc.

But the only reason I can imagine of why people want to deploy to them is because they are free and quick hosting -however zeit:now + cloudflare accomplishes the same - with much more coolness

@yn5
Copy link

yn5 commented Jan 30, 2017

@balupton Not really, if you have a static site which does not have to render the app or fetch data on the backend before it is sent to the server you can gain a lot of speed. This is the main reason I make static web-apps.

@stretchkennedy
Copy link

@yn5 I think he's talking about using cloudflare's caching.

For myself, the reason I want to render a static site is to lower the attack surface and to consume fewer resources. Deploying nodejs requires keeping more dependencies up to date than just deploying nginx, and wastes a perfectly good VM even if you put it behind cloudflare.

@bguiz
Copy link

bguiz commented Feb 9, 2017

@balupton But the only reason I can imagine of why people want to deploy to them is because they are free and quick hosting -however zeit:now + cloudflare accomplishes the same - with much more coolness

I agree with the reasons mentioned by @stretchkennedy and @yn5 - but I'll also add that the over-arching goal should be to move towards being more permissive; rather than to restrict the options. If a particular site is truly static in nature, then why preclude having the option of being able to serve from a static host?

Additionally, enabling zeit to work with a flow that one has already invested time in setting up and tweaking (e.g. in your CI/ CD pipeline), rather than having to set up a new flow, is a win.

@matthewmueller
Copy link
Contributor

matthewmueller commented Feb 21, 2017

I'd like to toss in my hat on how I think this could work really well:

static getInitialProps ({ build, req }) {
   if (req) {
      // server-side
   } else if (build) { 
      // static build (can contains parameters about the page build)
      // this happens at the time of the build (next export)
   } else {
      // client-side
   }
}

next export will generate HTML & JSON representations of each top-level page component.

  • The HTML representation will be used to serve the initial request
  • The JSON representation will be used to asynchronously navigate around via <Link href="...">

The cool thing about this is that you can pull in markdown files and other resources (even pre-render a page) all from within that build == true condition.

@jstcki
Copy link
Contributor

jstcki commented Feb 21, 2017

@matthewmueller would it be possible to eliminate code from getInitialProps() on build?

Let's say you use an API to fetch live data during development and you want to "bake" it into a static build (both in the HTML and JSON representation of a page), to eliminate any API requests in production. This would be awesome for a collaborative workflow.

To optimize the output you'd probably then remove the dependency on whatever API library you use to fetch data in getInitialProps() during dev/build time because you can basically just replace it with the API response.

static async getInitialProps ({ build, req }) {
  if (build) { 
      return myCoolAPILib.fetch('foobar.csv') // Probably load myCoolAPILib through webpack's async import()?
   }
}

gets turned into:

static async getInitialProps () {
  return {
    // Response from myCoolAPILib
  };
}

@kbingman
Copy link

So how would you handle code splitting? Right now, for dynamically rendered pages, Next requests a JSON file with the components. Would these be statically published as well?

@matthewmueller
Copy link
Contributor

@kbingman yep, i believe the json versions are built and written to the filesystem anyway.

@tom2strobl
Copy link

From a dev-ops, scaling, speed and pricing point of view, nothing beats a static page on S3. So this feature is actually super important for us.

@rauchg
Copy link
Member Author

rauchg commented Mar 29, 2017

@kbingman those will be statically generated indeed as well

@jstcki
Copy link
Contributor

jstcki commented Mar 29, 2017

Is anyone actively working on this yet? If not, I might give it a shot since I'm very interested in this feature.

I did some spelunking in the next.js codebase and got an extremely rough proof-of-concept working by basically adding another step to the build using the server's renderToHTML function.

As far as I can tell it's pretty straight-forward. One of the bigger challenges will be to deal with dynamic routes like /posts/:id, especially if they're not referenced by links in the HTML (which would make them un-crawlable). So probably the user should be able to provide a static list of routes.

@schoenwaldnils
Copy link
Contributor

@herrstucki

One of the bigger challenges will be to deal with dynamic routes like /posts/:id, especially if they're not referenced by links in the HTML

Thats what I'm looking for. I hope to find a way to generate pages from markdown-files, and list them in a dynamic-navigation.

@kylehotchkiss
Copy link

@schoenwaldnils

I agree with this. Would be awesome to have a react-powered Jekyll replacement. (I realize much of that blog functionality is out of scope). But this definitely would make next.js a solid platform for a larger audience who might want to throw things on gh-pages or S3.

@schoenwaldnils
Copy link
Contributor

@kylehotchkiss Absolutely! This is exactly what I currently have in mind.
The main problem in my case(s) is, that the site still should be maintainable by the marketing-team through cloudcannon, prose.io or something like that.
And I think markdown with configurable meta is still the best way to add easy content-editing.

@matthewmueller
Copy link
Contributor

matthewmueller commented Mar 30, 2017

@herrstucki I'm working on this a bit, happy to collaborate on a branch. definitely need this feature as well. I think this can be done entirely via the plugin system, then we can make it nicer / a bit more native later.

@schoenwaldnils you could achieve that sort of functionality by passing a { build: true } or any other indicator during the static build step to getInitialProps().

Regarding routing, at least for an initial implementation, I think only the development server needs to be route-aware, which you can achieved with a custom server. When you export to static, a service like Cloudfront or netlify can take the routing from there and you can use <Link href="/post" as="/post/4">...</Link> to do the dynamic stuff.

@matthewmueller
Copy link
Contributor

PR has landed: #1576 💥

@arunoda
Copy link
Contributor

arunoda commented May 15, 2017

Now we've "next export" support built into the core.
See: https://zeit.co/blog/next3-preview
Thanks everyone for all the help.

@arunoda arunoda closed this as completed May 15, 2017
@dejanr
Copy link

dejanr commented May 15, 2017

Great to see this happend. Amazing work guys!

@juliandavidmr
Copy link

Hi, next export generates a subfolder called _next, is there any way to automatically rename it?

@arunoda

@ghost
Copy link

ghost commented Aug 16, 2017

How do you guys handle DOM events with next export? Thx!

[EDIT] on Mac I need to manually change all src="/_next/xxxx" paths to src="./_next/xxxx"

@arunoda

@adibas03
Copy link

adibas03 commented Jan 29, 2018

@juliandavidmr @sbe88
You need to set the assetPrefix variable in the next.config.js file.
you can also look through these for better explanation.
https://medium.com/@anotherplanet/git-tips-next-js-github-pages-2dbc9a819cb8
https://medium.com/@adibas03/next-js-github-pages-contd-42a1dd47f6bc

@lock lock bot locked as resolved and limited conversation to collaborators Jan 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests