What is the difference between `next export` and `next build` in Next.js? - deployment

I have developed a web app that uses Nextjs app for the frontend and a Python (Django) API server as the backend. Most of my front-end pages have API calls to my backend server (in ComponentDidMount or in response to user actions like button clicks).
I want to deploy this app to my server. I am using Nginx as the reverse proxy. The backend deployment is sorted. I am confused about deploying the nextjs app.
After reading the docs I figured there are 2 ways to do this:
Run next build and then next start. This will start a nodejs server on port 3000. I can channel traffic to this port using Nginx.
Run next export. This will generate an out directory. I can channel incoming traffic to this directory using a reverse proxy like Nginx.
Which of the 2 options should I use? What are the differences?

Answering my own question with the help of the answer I received on the NextJS discussions forum link here
Basics of next build, start and export
next build builds the production application in the .next folder. You need to run this command irrespective of whether you want to run next start or next export.
After building, next start starts a Node.js server that supports hybrid pages, serving both statically generated and server-side rendered pages.
next export will export all your pages to static HTML files that you can serve with any host. This is similar to what create-react-app does, but you can still build dynamic pages at build-time with exportPathMap.
Note: Statically generated pages, using next export, are still reactive i.e. any dynamic JS code, which updates your pages at run time, will continue to run as usual (like any other ReactJS app). Next.js will hydrate your application client-side to give it full interactivity. Its just that the dynamic section of the page will only be rendered in the browser at run time and hence it won't be available to search engine crawlers.
When to use next export?
next export is recommended if you have some dynamic pages which need to some data to be fetched only at 'build' time. It is perfect for pages like landing pages, blogs, news articles etc, or for other kinds of pages which are updated only during code builds. You can setup a background task to build your code at regular intervals if your page data needs to be updated more frequently. This will speed up your 'first paint' speed and also provide the entire page data to search engine crawlers for indexing.
When to use next start?
If you do not need any data fetching at build time i.e. your pages are rendered dynamically at run time then you should use next build and then next start. This will also generate static HTML for sections of your page which are not dynamic. This will speed up the 'first paint' time of your pages. See this Automatic Static Optimization.

next export, also produces an optimized production ready build, but it builds fully static app, which means only html, css and javascript but no server-side code.
Since there is no server side code, you do not need a server to host your app. This makes hosting your app easier and cheaper because you dont need to maintain and scale a server. There are plenty of hosts in the market which offers very good pricing.
Since next export builds a static app, it means you cannot use api routes, server-side functions therefore you cannot revalidate. Revalidation means, your app will be checking database for a certain of time that you specify. Let's say you have a blogging app, you save your blog posts to database, with server side coe, you get those on server side, pass them to the client and client renders the posts and with revalidation option set, your app would automatically check the database if the content changed. Since you cannot use this feature, anytime content of your app changes, you have to redeploy your app.

Related

How to load all pages at startup?

With the Ionic 4 framework and using the PWA.
I would like all the pages, the whole project is cached as soon as the first page is loaded.
In fact, I would like the user to log in once and then offline to access all pages.
Because currently, only the first page is displayed ..
You are talking about "multiple pages" in a sense that is implying that your implementation does not use the App Shell model.
Probably, you need to do the following things:
Implement the App Shell
Implement navigation between the different content pages of your app
Implement the static content pages (I assume they are static, since you want to primarily use them offline)
Have the service worker cache the whole bunch.
All the content is now cached on first launch. Dynamic content fetched from the server would of course still require an internet connection.

How do you do continous deployment in an AJAX application with lots of client side interaction and local data?

We have an app that is written in PHP. The front end uses javascript heavily. Generally, for normal applications that require page reloads, continuous deployment is not really an issue, because:
The app can be deployed with build tags: myapp-4-3-2013-b1, myapp-4-3-2013-b2, etc.
When the user loads a page (we are using the front controller pattern), we can inject the buildtag and the files are loaded from the app directory with the correct build tag.
We do not need to keep the older builds around for too long because as the older requests finish, they will move to the newer build tags.
The issue with database and user data being incompatible is not very high as we move people to the newer builds after their requests finish (more on this later).
Now, the problem with our app is that it uses AJAX heavily for smooth page loads. In addition, because there is no page refresh at all when people navigate through the application, people can keep their unsaved data in a their current browser session and revisit it as long as the browser has not been refreshed.
This leads to bigger problems if we want to achieve continuous deployment:
We can keep the user's buildtag in their session (set when they make the first request) and only switch to newer buildtags after the logout and login again. This is obviously bad, because if things like the database schema changes or the format of files to be written to disk changes in a newer build, there is no way to reconcile this.
We force all new requests to a newer build tag, but there is a possibility we change client side javascript and will break a lot of things if we force everyone with a session onto the new build tags immediately.
Obviously, the above won't occur with every build we push and hopefully will not happen a lot, but we want to build a fool proof process so that every build which passes our tests can be deployed. At the same time, we want to make sure that every deployed and test passing build does not inadvertently break in clients with running sessions cause a whole bunch of problems.
I have done some investigation and what google does (at least in google groups) is that they push a message out to the clients to refresh the application (browser window). However, in their case, all unsaved client side data (like unsaved message, etc) would be lost.
Given that applications that uses AJAX and local data are very common these days, what are some more intelligent ways of handling this that will provide minimal disruption to users/clients?
Let me preface this that I haven't ever thought of continuous deployment before reading your post, but it does sound like quite a good idea! I've got a few examples where this would be nice.
My thoughts on solving your problem though would be to go for your first suggestion (which is cleaner), and get around the database schema changes like this:
Implement an API service layer in your application that handles the database or file access, which is outside of your build tag environment. For example, you'd have myapp-4-3-2013-b1, and db-services folders.
db-services would provide any interaction with the database with a series of versioned services. For example, registerNewUser2() or processOrder3().
When you needed to change the database schema, you'd provide a new version of that service and upgrade your build tag environment to look at the new version. You'd also provide a legacy service that handles the old schema to new schema upgrade.
For example, say you registered new users like this:
registerNewUser2(username, password, fullname) {
writeToDB(username, password, fullname);
}
And you needed to update the schema to add the user's date of birth:
registerNewUser3(username, password, fullname, dateofbirth) {
writeToDB(username, password, fullname, dateofbirth);
}
registerNewUser2(username, password, fullname) {
registerNewUser3(username, password, fullname, NULL);
}
The new build tag will be changed to call registerNewUser3(), while the previous build tag is still using registerNewUser2().
So the old build tag will continue to work, just that any new users registered will have a NULL date of birth. When an updated build tag is used, the date of birth is written to the database correctly.
You would need to update db-services immediately, as soon as you roll out the new build tag - or even before you roll out the build tag I guess.
Once you're sure that everyone is using the new version, you can just delete registerNewUser2() from the next version of db-services.
This will be quite complicated to make sure that you are correctly handling the conversion between old API and new API calls, but might be feasible if you're already handling continuous deployment.

How to replace single web resources locally?

I am often working with websites to which I have no code access but for which I need to test javascripts, ajax calls and other resources in locally modified versions.
As an example I needed to test a new creative code originally coming from a DoubleClick server. Instead of working directly on DoubleClick and loose a lot of time waiting for my changes to take effect I needed to manipulate a local copy of that javascript resource.
So I changed my /etc/hosts to point the DoubleClick server to localhost where I run a local web server. This way I was able to test a local script instead of the original.
Of course this redirected all resources and not only the one i was interested in what often results in either weird behaviour as resources become unavailable or a lot of effort on my part to make them available.
Is there a way to replace a specific URL by redirecting it to a local file/URL and let all the others from the same origin be untampered?

GWT application freezes when new version is deployed while using it

While using the GWT application, I deployed the new version of the application.
Once deployment is complete my application freezes until I do the full refresh.
I originally thought this was caching problem, so I assigned all the files to be no-cache by setting all response headers using the filter. But still with this filter application freezes when I deploy a new version.
What could be a cause of this?
What I am trying to achieve here is to be able to deploy a new version of GWT application while user is using the application. This means when the JavaScript changes I want user to get it from the server instead of using the cached one without any glitch (maybe slow response time since request need to go to the server in this case).
Note:
This is observed when deployed with the changes in the code, so I am
guessing one of the cache.js file.
When deployed without any changes to a code this is not observed.
Your question is not clear because it does not tell which situation you are in:
You deploy the new GWT app and you want the new server-side to respond to the old client-side.
You deploy the new GWT app and you want the client browser to immediately replace the GWT client with the new version.
I would like to speak about situation 2, first. I am thinking you came from a background of servlets and JSP, plus dynamically generated HTML and Javascript. In those env, the client is immediately replaced everytime your client places requests the server. That is because the client UI is refreshed by new response generated by the server.
In GWT, the root panel is not refreshed. The root panel is held by the hosting html page. If the hosting html page is not refreshed, the GWT client will forever be the old version. That is the very idea of AJAX and GWT. You don't want to have to refresh the web page and yet allowing the web page to continuously emit/receiv async requests/responses.
You might be reminded that GWT is compiled into javascript.
In order to get the new version, you have to refresh the web page. There is no way in GWT technology for the new javascript to sneak into the browser to replace the old sets of javascript, unless you refresh the page.
The script tag source link is already read when the GWT javascripts are loaded. Those links will not be reread unless you refresh the page. If those links are not re-read, then the new javascripts will never be reloaded.
You need to detach your JSP/servlet experience when dealing with AJAX.
Back to situation 1 ..
Since the new GWT UI version was not loaded, because you did not perform a refresh, you would have incongruences between the data structure expected by the old UI version with that of the new server-side version. If you can guarantee the stability of RPC or client-server data structure and sequences of exchange, I believe you should not have a problem.
However, with GAE, the serialization id is important. You may have changed the data structure of a POJO without updating the serialization id. That would confuse the GAE client-server traffic, because ... hmmm ... I can faintly recall the exact sequence of problem I had faced - You better read up on GAE pojo serialization id yourself.
I also had such problem. In such case you should have one table which keeps every new upload information. And also you should have one async request (maybe in your EntryPoint) for checking whether you have new upload or not.
public void success(String version) {
if(!Cookies.getCookie("version").equals(version)){
Window.open(currentUrl, "_self", "");
}
}
This is what i've done and working without any problem...
The problem is from your web server not the GWT itself. You should see if your Web Server supports hot-deployment or not and how it works with it.
UPDATE :
For example Tomcat prior to version 7 does not support Hot-deployment and you have to restart the server on every update whereas Tomcat 7 supports Hot-deployment and you only have to reload the page to get the new module.

How To Deploy Web Application

We have an internal web system that handles the majority of our companies business. Hundreds of users use it throughout the day, it's very high priority and must always be running. We're looking at moving to ASP.NET MVC 2; at the moment we use web forms. The beauty of using web forms is we can instantaneously release a single web page as opposed to deploying the entire application.
I'm interested to know how others are deploying their applications whilst still making them accessible to the user. Using the deployment tool in Visual Studio would supposedly cause a halt. I'm looking for a method that's super quick.
If you had high priority bug fixes for example, would it be wise to perhaps mix web forms with MVC and instead replace the view with a code-behind web form until you make the next proper release which isn't a web form?
I've also seen other solutions on the same server of having the same web application run side-by-side and either change the root directory in IIS or change the web.config to point to a different folder, but the problem with this is that you have to do an entire build and deploy even if it were for a simple bug fix.
EDIT: To elaborate, how do you deploy the application without causing any disruption to users.
How is everyone else doing it?
I guess you can run the MVC application uncompiled also? and just replace .cs/views and such on the run.
A websetup uninstall/install is very quick, but it kills the application pool.. which might cause problem. Depending on how your site is built.
The smoothest way is to run it on two servers and store the sessions in sql server or shared state. Then you can just bring S1 down and patch it => bring s1 back up again and bring S2 down => patch S2 and then bring it up again. Al thought this might not work if you make any major changes to the session parts of the code.
Have multiple instances of your website running on multiple servers. The best way to do it is to have a production environment, a test environment, and a developement environment. You can create test cases and run the load every time you have a new build, if can get through all the tests, move the version into production ;).
You could have two physical servers each running IIS and hosting a copy of the site. OR you could run two copies of the site under different IIS endpoints on the SAME server.
Either way you cut it you are going to need at least two copies of the site in production.
I call this an A<->B switch method.
Firstly, have each production site on a different IP address. In your company's DNS, add an entry set to one of the IPs and give it a really short TTL. Then you can update site B and also pre-test/warm-up the site by hitting the IP address. When it's ready to go, get your DNS switched to the new site B. Once your TTL has expired you can take down site A and update it.
Using a shared session state will help to minimise the transition of users between sites.