How to build Nuxt with specific content - node.js

I build a multi-site where one frontend can request information from the backend based on the domain. Code and style is always the same and some routes too, but content must be dynamic per domain.
Everything works fine otherwise, but I don't know how to run Nuxt so that CSS / Tailwind / JavaScript is in production mode and SSR + CSR will handle whatever comes from the backend. Normal pages can't be static pages and I don't know all routes needed so those need to be generated when the backend sends data.
I tried to follow Nuxt server tutorials, but no luck yet. I think I have to run Express or module nuxt-start, but those gave FATAL No build files found in .nuxt/dist/server.
How can one run Nuxt which can handle multiple domains and different content? npm run dev works as I want for production working, but needs to be more optimized and faster. What kind of configuration I need?

To build for production, you need to either do:
yarn generate (target: static)
or yarn build (target: server, aka the default value)
then you should yarn start (on the production server).
As for having custom content, this one should probably be dependent of some env variables to decide where to fetch the content from, and then using nuxtServerInit to populate your Vuex store: https://nuxtjs.org/docs/2.x/concepts/nuxt-lifecycle
Of course, you could also do it elsewhere, like in serverMiddleware or at build time if you use Docker.
As for the routes, you can keep them dynamic and populate them with the related data.

Related

Is Create-React-App a Server Of It's Own?

I am pretty experienced with NodeJs and Express, but I'm a beginner in ReactJS.
I usually use ejs and deploy my server on Express like this and route server-side.
app.get("/", (req, res) => res.render("index.ejs");
app.get("/contact", (req, res) => res.render("contact.ejs", { data: data });
Something like this.
However, working with React (create react app), I find myself not using express at all for routing and only serve an API.
Create React App apparently already has a server (localhost:3000 by default) and I can perform client side routing directly there.
Should I deploy my server on a client-side framework, React?
I don't even need to serve static files on express.
Hope you understood me, thank you for your help :)
First of all react is a library and second of all, when you say that it has a server that means it's a development server, for reviewing the results while you're working on it locally (means when you are building your application, you need to see how it looks in real-time). It's not for production use or included in the build output. Now let's say your application is ready and you want to deploy it, then you run a build command which does the following for you
transpiles JS code
bundles code and assets
uses cache busting techniques for assets
removes dead code
and you will deploy your application on a server, so that it can be accessible to clients
I don't need to serve static files on express, explanation below
In modern-day websites, we don't have to use views because react comes into the picture and takes care of the clientside-UI that the user interacts with, so you are right that we don't have to use static files in express anymore but if you have a use case where you have to use it then you can use it, no one is stopping your from doing that
and lastly you can have your own node js server as well which your front end will be talking too, not for views but for data that is stored in database that you want to fetch and display it to the user
React by itself just create static html-css-js files, but for testing purposes, they have also included this handy way (localhost:3000 pipeline) to view the built files. Technically you don't need to use it, just use the build script, then set up an express server to serve the files from "build" folder, and it does the same thing.
About client side routing, basically what happens is the entire page gets downloaded client-side, and it uses the value in url box to show or switch to certain screens. This is why its called "Single Page Application", you are serving a single page to the client upfront with all the static code. Compare this to express-ejs where you serve static code conditionally, depending on the address.
Take a look at CRA's docs for more info about deployment.

How do you manage repositories for production/deployment of Node-React app?

Not long ago , we used to have server render pages and then React came for client side rendering and single page application.It introduced virtual DOM's and changed the way we write our code.
We require all these react libraries and install them as dependencies before writing our codes. Now we can break into many components , have many css and scss files including images. But at the end we will build the files, make compact bundle and serve from build folder.
Express get route
app.get('*', (req,res) =>{
res.sendFile(path.join(__dirname+'/client/build/index.html'));
});
Heres, What I have understood :
Build folder is the place where webpack combines all the files and create minified bundle ready for deployment. That file is basically simple HTML and JS files which every browser can understand. As all the browser doesn't understand ES6 and much more, we have to convert all these files into plain language that every browser can understand.
Also, webpack-dev server is only for development purposes and we won't be running it into production.
Is virtual DOM/Real DOM just for development purposes? or
are those react libraries also trans-piled while building the minified files? If later is the case , react is run on background mode on client's browser? I want to know how react takes care of client side routing after the building the app.
How do you manage github repositories for Node-React app? Do you keep two different repositories one for front end and other for back-end? Whats the industry standard?
If you keep two repository, how do you deploy the front-end code? As you can't run the webpack-dev-server into production. Nor you can specify the public static (build folder) in your back-end(express server) as they are separated in two repos. How does, either the integration of these two repositories take place( lets say we have two AWS EC2 instance, one for each) or front-end get served from the front-end repo??). Can you actually use something like npm serve in production ??
what am I trying to do ?
I want to deploy my node-react app on AWS. I have only one repository on github. I have one folder "client" inside my repo where all the react code sits with its package.json file. All the other files for server are inside root folder (server doesn't have its own folder and files are scattered inside root folder). So there are two package.json files, one inside root folder for server and one inside client folder.I am planning to run my-node app on a docker container.
Please help me understand the core concepts and standard practices for code hosting and deployment keeping large scale enterprise application in picture.
I would not go into explaining all the points in your question here because, #Arnav Yagnik and #PrivateOmega have both done a brilliant job at explaining most of them. I would definitely recommend you to read their answers properly and read the links provided for more information before reading this answer.
I would like to address your question of deploying a Node-React application. In production, generally, we have different deployments (or "repositories" as you mention in your question) for both the front-end (React) and back-end (Node). This allows your back-end to sit in an EC2 instance, for example, with auto-scaling to make sure that it can cope up with all the requests coming in.
As mentioned in the previous answers, and in your question as well, webpack compiles and minifies the React files into simple HTML and JS files, which most browsers can run (I'm not going to explain VirtualDOM here because it has already been perfectly explained in other answers). You would then take these minified files and serve them from an S3 bucket for example, because again, it is a single page application (also discussed in the other answers) and the business logic is already in the minified JS files and its just simply sending all requests to your back-end server.
Now for front-end, you can use TravisCI for example to deploy the build folder (the one you talk about in your question) to an EC2 instance and serve your files using NGINX or if you can configure a CDN deployment properly, you can serve the files from an S3 bucket for the most optimal performance.
You can think of serving the React application like sending a cryptic block of code to your user's browser. Now you can deploy this cryptic block of code to a publicly available S3 bucket, and serve it from there. Again, because of webpack and minification/uglification, no on would be able to make any proper sense of what your original code was, remember that you can still access all the code in Chrome's Sources tabs for example.
I would like to address this with different approach.
Server Rendered Pages : The concept has not changed, server when encountered with a DOC request it has to respond with a html. Now HTML may or may not contain scripts(can be either inline or a external server address). In case of question's context you can still ship HTML where it will download scripts that you have written(may include react or not). for most cases you can ship empty html with scripts tags which will download the scripts over network and execute them which would contain all the rendering logic.
To Answer your questions :
1st : There is no background mode in a single threaded JS(unless we want to talk about workers but we can leave them out for this discussion). By writing in code you are not interacting with any DOM. You are instructing your components(extended by React) when to change their state and when to re-render(setState). React internally calculates the virtual DOM and compare to Real DOM to calculate actual changes that are to be made on Real DOM(this is very abstract answer, to get more understanding please read react docs, Baseline here is you are not interacting with any DOM just instructing React core library when to update and what is the updated state)
2nd : If you want to support SSR(server rendered pages). I would suggest to make 2 folders , client(this would include all client components and logic) and server(would include all server side logic) with different package.json as packages differ for both applications.There is no such industry standard here, what floats your boat should work but generally making directories based on logical entities should satisfy separation and maintainability, if in future you think you want to fork out server and client in separate repos , it would definitely make the process easy.
3rd : You shun running webpack-dev-server in production. Files are generally not obfuscated hence payload is heavy(not to forget your written code is out there). Even if you want to make different repos, server can spit out html and html can request scripts with your client server.
How to deploy : Deploy your code and run :
node server/app.js
and in app.js you can write the location block what you have mentioned.
P.S. : If you just need a server with that location block. do you really need a express server? You can upload the client build to a CDN and route your domain to serve index.html from the CDN(s3 bucket can also be used here)
I would like to start off with clearing up the terminologies as much as I can.
Like you said server rendered pages was a more prominent standard in the past, but it hasn't changed at all with the introduction of React, because even React has the support for Server rendering or SSR, which means HTML pages are generated at server side and then served to clients using browser.
And client side rendering means, a HTML page is loaded to browser and then javascript code renders things on top of those HTML pages and make them interactive.
And single page application concept is that we have only a single HTML file or base HTML page on top of which based on user interactions and data from server it is rewritten continuously.
Virtual Dom is an amazing concept introduced by React. React library code recreates the structure of all elements(called DOM elements) of a HTML page in the memory in a tree form. This enables React algorithm called Fiber to reconcile appropriate changes as per route update or any other changes first on this tree like structure before translating them onto the real elements in the HTML page.
Babel is a transpiler to transpile latest features that browser engines haven't started supporting to code that they can understand, usually ES6+ code into pre-ES6 because all browser supports that. In React application, if you have written application using JSX syntax, babel supports transforming JSX into normal javascript also.
Yes, breaking up of pages into many components is possible due to compositional nature of components by React which means we can build complex things by combining small and more focussed things.
At the end before serving it to end users, we can't have web application lag due to the huge size of code, so during the build process, things like minifying(removing whitespace etc) and other optimization like combining multiple javascript files into one etc are done, and then compact bundle is served from build folder like you said.
Yes, build folder is where webpack does the minifcation and combination to create a bundle as small as possible. It is basic HTML and JS files that is understood by every browser, and if the code contains something that a particular browser doesn't support, appropriate support code or something called polyfill is also bundled with it. Technically you can't say browsers only understand pre-ES6 code because a lot of browser engines have implemented plenty of ES6 features already.
Webpack dev server is just used to serve a webpack application over a port like a node.js server and gives us features like live-reloading which is needed when you constantly make changes to your application codebase and it isn't needed at production because like we said previously, at production time it's just HTML and JS and nobody ever makes any changes on these files.
Virtual DOM is a memory representation or concept used by React Code just like we have stacks and queues and it not just used at development time. Yes and No. Because I think appropriate parts of react source code which is required to run the application would also be bundled before generating the production bundle.
I would say, don't have a preset way of things, because it is totally upto the developer and the team, because I have seen people using 2 seperate repos because frontend people work on frontend things whereas backend people work on backend things. But there's also a case when everyone's a fullstack developer and you can Technically have it in a single repo with a single package.json and use the backend to serve the frontend files and you have to manually install each react dependency and cannot directly use CRA or create-react-app like generator.
What has 2 repositories to do with front-end deployment in production? You don't need to run webpack-dev-server to server files in production. You can create a production bundle and then setup any http server to serve the generated bundle.
Regarding your current scenario I would say instead of having 2 package.json, you can go with a single package.json and install all dependencies together or go with a monorepo approach using something like lerna or yarn workspaces.
But for a total beginner I would suggest 2 separate repositories to encounter less problems.
And a bonus point if you are not aware, you can write React in pre-ES6 code and also without JSX as well.
1) virtual DOM is basically to say that you are calling a function of react not the actual function which does manipulation on the real DOM
like this one
document.getElementById("demo").innerHTML ="Helloworld"
modifies the actual dom
but this
ReactDOM.render(
<HelloMessage name="Taylor" />,
document.getElementById('demo')
);
if you see this properly you aren't doing anything directly on the dom you are just giving the react function control to do things , internally react take cares of modifying the that dom element demo whenever the react wants to re-render it based on its own logic which is what they claim as optimized which is why people use it in first place. Yes when you build your code with webpack it does include react in it which is part of that minified code, so if you see any of the error stacktrace in development you do see react is the starting point for it
2) I think its a choice to be made, as there are not restrictions on this
3) Coming to deployment , In general if you want use nodejs you might choose expressjs server type of deployment but otherwise generally its better to use a high performance server like Nginx or Apache or else if you just don't want to get into this whole drama of things people generally use heroku based deployment or else people are using special platforms like netlify,surge.sh these days (its super easy to deploy on these platforms).
I believe others have done a pretty good job explaining the React Virtual DOM. In a simple and practical way, I’ll attempt to explain how I (would) manage the deployment of a dynamic website (including medium-sized enterprise systems) using NodeJS and React. I’ll also attempt not to bore you.
Imagine for once that React never existed and that you were building a traditional Server-Side Rendered application. Each time the user hits a route, the controller works with the model to perform some business logic and returns a view. In NodeJS, this view is usually compiled using a template engine such as handlebars. If you reflect for a second, it becomes obvious that the view could be any html content which is then sent back to the browser as a response.
This is a typical response that could be sent back:
<html>
<head>
<title>Our Website</title>
<style></style>
<script src="/link/to/any/JS/script"></script>
</head>
<body>
<h1>Hello World </h1>
</body>
</html>
If this response hits the browser, obviously “Hello World” is displayed on the screen.
Now, with this simple approach, we can do powerful things!
OPTION 1:
We can designate one controller to handle all incoming routes app.get("*", controllerFunc) and render one view for our entire server.
OPTION 2:
We could ask multiple controllers to handle different routes and render route-specific views from our server.
OPTION 3:
We could ask multiple controllers to handle different routes and generate pages on-the-fly (i.e. dynamically) from our server.
If we were building a traditional web application, option 3 would be the only reasonable standard. Here, pages are generated dynamically for different routes. However, with option 1, we can produce a quality Single-Page Application where the response sent to the server is an empty html page but with the built JS script that has the ability to manipulate the DOM – Yes, React! Here’s what such a response might look like:
<html>
<head>
<title>Our Website</title>
<style></style>
<script src="/link/to/any/JS/script"></script>
</head>
<body>
<h1>Hello World </h1>
<div id="root"> </div>
<script async type=”text/javascript” src="/link/to/our/transpiled/ReactSPA.js"></script>
<!--async attribute is important to ensure that the script has access to the DOM whenever it loads. This also makes the script non-blocking -->
</body>
</html>
Clearly, we’re giving all the responsibility to the generated SPA and all routing logic is handled on the client-side (See, react-router-dom). On the server side, we can introduce the concept in option 2 and tweak NodeJS route handlers to listen to another specific route for any REST API communication. If you’re familiar with NodeJS, the order in which routes are registered either by app.get() or app.post() matters.
However, using option 1, we can quickly become limited and only able to serve one Single-Page application from that server. Why? Because we have asked one controller to handle all non-API incoming routes and render one view. We also risk serving an unnecessarily bloated JS file. Users are served the complete website when all they probably wanted was just the landing page.
If we look to the option 2 though, we can tweak things a lot more and serve multiple Single-Page Applications for different routes, all from our server. This approach helps to reduce the sizes of the JS build being sent to the browser. A typical example would be a website that has a welcome page (or an introduction directory), a login page and a dashboard.
By assigning controllers for different routes, we can build SPAs uniquely for those routes. SPA for the intro page, another for the login page, and then another for the dashboard. Yes, the browser would have to load while transitioning between the three, but at least we highly increase initial render time for our website. We can also use the more secure option of cookie for authorization rather than the less secure option of storing session tokens on localStorage.
In a more advanced setting, we could have dynamic websites with different React components rendered as widgets within the dynamically generated page. Actually, this is what Facebook does.
The way to build such SPAs or components is pretty simple. Start up a react project and configure webpack to render the production-ready JS file into your preferred public static directory within the server-side repo. The <script> specified in the view can then easily load these built react components since they exist within the scope of the server-side’s public directory.
In essence, this means one repo with several client directories and one server directory where the destination of the production build files to be generated by webpack for each client project is set to the server’s public static directory. So, each client side’s directory is a project (either full SPA or simple React Component as a widget) with it’s own webpack.config and package.json file. In fact you can have two separate config files – production and development. Then, to build, you use npm ~relevant command~ for either production or development build.
You could then go ahead to host it the way you would host any NodeJS application. Because, the main application is the NodeJS - that's where the server is. Replace NodeJS with PHP and Apache/NGINX, the concept still remains the same.

Vue/Webpack + Express (MEVN): URLs for API calls, development vs production

Building a MEVN application.
When running in my development environment, there are two servers running concurrently: webpack-dev-server at localhost:8080 serving up the Vue/Webpack-based front-end client application, and localhost:8081 serving the Node+Express back-end application which provides the RESTful endpoints that the client consumes.
When deploying for production, however, the Node+Express server, in addition to providing those endpoints, also serves the static Vue/Webpack application as described in this answer.
My issue is this: To call one of those endpoints from the client in the production environment, since they're all coming from the same server, I can just load /route/to/my/endpoint?param=val or similar. In the dev environment, since they're two separate servers, I'd load http://localhost:8081/route/to/my/endpoint?param=val instead.
It seems like there must be some trivial way to include the http://localhost:8081 in the code when running the webpack-dev-server, but omit it when building for deployment.
I've seen a few articles talking about the publicPath webpack config item, but none of them are quite addressing this issue in a way that makes sense to me.
What's the "right way" to do this?
Figured it out a bit more quickly than I expected to.
An easy way to do this is with Webpack's definePlugin mechanism, which is nicely described here.
Essentially, in the plugins section of my webpack.dev.conf.js I added this:
new webpack.DefinePlugin({
__API__: "'http://localhost:8081'"
}),
and in the same section of webpack.prod.conf.js I added this:
new webpack.DefinePlugin({
__API__: "''"
}),
Then, in a vue file, when I wanted to hit an endpoint, the call would look like this:
axios.get(__API__ + '/myendpoint')
Critical thing that's mentioned in the above article but easy to miss: The webpack engine does exact text replacement of the identifier, in this case, __API__, and since my code there is expecting a string, it must be defined in the DefinePlugin so it's got quotes around it. An alternate way to do this would be __API__: JSON.stringify("http://localhost:8081") or similar.

Environment Variables in Angular2

So I have an angular 2/4 app, with a node server.js to serve it. I want to access an environment variable (backend endpoint is localhost for dev and another endpoint for prod). If it matters, this app (as well as the backend app) are meant to be deployed to Heroku.
I have tried finding a solution to this, but everything I found seems to lead to using multiple environment.ts files (1 for each configuration), and then swapping between them based on the ng build flag --env. But I am apprehensive about this solution as it seems to mix configuration and source code. I also would like to avoid (if possible) being required to re-build/re-deploy whenever an endpoint/config changes.
In Spring Boot, I'm used to using config like ${PORT:8080} in the properties files. Though I've also created multiple .properties files in the past so I understand that sometimes it's just simpler/cleaner to do so.
In node, I'm used to doing env variables like process.env.PORT || 8080. Since my angular app is served by a node server.js, I would think I should be able to do something similar. But when I try using process.env in my environments/environment.ts file, I get the error Cannot find name 'process'.
So my question is essentially, if I am required to create multiple environment property files or is there an alternative.
Thanks
You basically have two choices, regardless of whether your config is stored in environment variables or in a config file on the server. Your clientside code needs it, so you either need for serve it as part of your assets bundle, or you have to fetch it as a separate request. That separate request could be an Ajax call or just a js file that gets served separately from the rest of the bundle.
I think ideally, the only difference between the production app and the nonproduction app on the client should be the data, the bundle density (in dev you don't want your stuff minified for example) and what url it's served from. Everything else should be discoverable from the source url, imo

prevent vue-cli (webpack) from picking up all non-file GET routes - sails environment

When creating a Vue project with vue init webpack project-name, setting it up, and finally calling npm run dev you can open your browser on localhost:8080 and see the default page. In fact, you can navigate to mostly any "non-file" path, such as /a/b/c-d, and Vue will still pick it up. The only paths that it didn't seem to pick up are the ones ending with .*, and ones ending simply with .. Examples are /a.js, /b., /c/d.png
I am trying to use Vue with a REST backend (Sails.js, using sails-generate-new-webpack-vue), which means I will have routes that will look like GET /api/users and similar. With that sails generator, a common webpack Vue project is generated, and some config files are changed in order to put the output of webpack onto the .tmp directory used by sails in order to actually serve files.
I tried looking at the source files and noticed that normally npm run dev calls node build/dev-server.js, as par package.json, but in there I don't see where it's actually redirecting everything to a single html file. That would already be helpful, but after a quick check I noticed that with my sails setup, that file is actually never used (plugged a simple console.log which never got ran).
How (or rather, where) does Vue redirect all "non-file" routes to a single path?
This may become clear as soon as I find out how and where it is, but otherwise, how do I change it and only make Vue pick up a specific express-route-like set of paths? As in, ideally I'd make it pick up routes such as /:username/profile
The answer doesn't have to be specific to sails, although if you have additional information, that might really help.
EDIT: steps to recreate
npm i -g sails sails-generate-new-webpack-vue vue-cli
echo "{\"generators\":{\"modules\":{\"new\":\"sails-generate-new-webpack-vue\"}}}" > .sailsrc
sails new test-project
EDIT: turns out it's sails specific
Turns out that what makes Vue pick every route is in build/dev-server.js, the history fallback API. That's great and I hope will help people looking for that answer, but with this specific setup, that file is never actually used, and I'm fairly clueless about what is being used. I do realize that there are very few people using the npm package I mentioned, but if anyone could give that a look, it would be extremely helpful!
EDIT: found exactly where to deactivate it
Had to look through a fair amount of source code, and saw webpack/node_modules/sails-hook-webpack-vue/index.js, just had to comment out lines 114 AND 120
As I see, you don't need the extra server configurations provided by the webpack template.
I will advice you switch to webpack-simple template.
The dev server is located in the build folder, a file called dev-server.js. It uses express to setup a local server to serve your files.
If you setup your own server to serve the files, do remember to server the build*.js files.
Eventually got it :D
The issue was with history-api-fallback middleware, which is normally toggleable in build/dev-server.js on a normal Vue project.
But with my setup, it was ultimately being introduced in the local webpack/node_modules/sails-hook-webpack-vue/index.js on lines 114 and 120:
sails.config.http.middleware.historyFallback = historyFallback();
...
sails.config.http.middleware.order.unshift('historyFallback');
which you just need to comment out.
Then you can indicate your routes as you wish in config/routes.js and make them point to index.html

Resources