You are on page 1of 38

UNIT V

Modularization and Web pack


Modularization in React
Modularity helps in code organization by splitting the
code into smaller parts. A modular architecture involves
breaking down a program into sub-programs called
modules. Note: The module refers to a component or set
of components that perform a specific task.
Web pack
Webpack simplifies the build process for React
applications. It allows developers to manage
dependencies and bundle files with ease. Webpack can
also optimize code and assets for production, reducing
the file size of the application and improving
performance
Web pack
• A tool for building JavaScript modules is called Webpack, often known as a module bundler.
It creates one file (or a few files) that your software uses to run from a variety of other files.
• It can do a lot of things, including the following:
• Supports resource bundling
• It monitors for modifications and repeats the jobs as necessary.
• You are able to use the most recent JavaScript features without having to worry about browser
compatibility by using Babel to convert to ES5.
• Conversion from CoffeeScript to JavaScript is doable.
• May generate data URIs from inline images.
• Enables you to use CSS files as needed.
• May operate a development web server.
• Can be used to quickly switch modules.
• You can divide the output files into many files to avoid having a big JS file load on the first
page click.
React Webpack Components

• We'll go through some of the most important webpack in react fundamentals


in the sections below.
• Loaders
• Dev Server (webpack-dev-server)
• Plugins
• Entry
• Output
Babel compiler
• Babel is a free and open-source JavaScript transcompiler that is mainly used
to convert ECMAScript 2015+ (ES6+) code into backwards-compatible
JavaScript code that can be run by older JavaScript engines. It allows web
developers to take advantage of the newest features of the language. [4]
• Developers can use new JavaScript language features by using Babel to
convert their source code into versions of JavaScript that a Web browser can
process. Babel can also be used to compile TypeScript into JavaScript.The
core version of Babel was downloaded 5 million times a month in 2016, and
this increased to 16 million times a week in 2019.
Commands to install
• Install webpack globally,
npm install webpack –g
• Install babel,
npm install babel-core babel-loader –save
babel-core--babel itself
Babel loader-will help us to use Babel together with webpack
Library Bundles
The fact that the bundle includes all of the libraries is a minor problem. The libraries
will not change often, but the application code will, especially during the development
and testing.
Even when the application code undergoes a small change, the entire bundle
is rebuilt, and therefore, a client will have to fetch (the now big) bundle from the server.

We’re not taking advantage of the fact that the browser can cache scripts when they are
not changed. This not only affects the development process, but even in production, users will not have
the optimum experience.
A better alternative is to have two bundles, one for the application code and another
for all the libraries. It turns out that a plugin called CommonsChunkPlugin, a webpack
built-in plugin, can do this quite easily.
module.exports = {
entry: './src/App.jsx',
entry: {
app: './src/App.jsx',
vendor: ['react','react-dom','whatwg-fetch'],
},
output: {
path: './static',
filename: 'app.bundle.js'
},
plugins: [
new
webpack.optimize.CommonsChunkPlugin('vendor','vendor.bun
dle.js')
],
module: {
loaders: [
{
test: /\.jsx$/,
loader: 'babel-loader',
query: {
presets: ['react','es2015']
}
},
WebPack Server as Proxy
• devServer: { },
• port: 8000,
• contentBase: 'static',
• proxy: {
• '/api/*': {
• target: 'http://localhost:3000'
•}
Hot module replacement
• To enable HMR, all we have to do is add a couple of command line parameters to the webpack-dev-server
invocation:
node_modules/.bin/webpack-dev-server --hot –inline
• import React from 'react';
• import ReactDOM from 'react-dom';
• import IssueList from './IssueList.jsx';
• const contentNode = document.getElementById('contents');
• ReactDOM.render(<IssueList />, contentNode); // Render the component inside 
• the content Node
• if (module.hot) {
• module.hot.accept();
• }
HMR as MiddleWare
• The way to do this is to install HMR as middleware in the Express server. As As
• discussed earlier, middleware is something that can intercept requests and do some
• special processing. The webpack-dev-middleware does the same work as it did as an
• independent webpack-dev-server: it looks for changes to files, and blocks requests to
the
• bundle until the changes are incorporated into the bundle. The webpack-hot-middleware
• does a similar thing for HMR. Let’s make these two middleware functions available by
• installing the respective modules:
• $ npm install --save-dev webpack-dev-middleware webpack-hot-middleware
few changes to the configuration for it to be used in an HMR environment. They are the
following:

• 1. We need additional entry points (other than App.jsx) so that


• webpack can build the client-side code necessary for this extra
• functionality into the bundle.
• 2. We need to add a plugin (which got enabled using the --hot
• command line for the webpack-dev-server) that generates
• incremental updates rather than entire bundles that can be
• sent to the client.
server.js: Use HMR via Middleware for
Development Convenience
• ...
• if (process.env.NODE_ENV !== 'production') {
• const webpack = require('webpack');
• const webpackDevMiddleware = require('webpack-dev-middleware');
• const webpackHotMiddleware = require('webpack-hot-middleware');
• const config = require('../webpack.config');
• config.entry.app.push('webpack-hot-middleware/client',
• 'webpack/hot/only-dev-server');
• config.plugins.push(new webpack.HotModuleReplacementPlugin());
• const bundler = webpack(config);
• app.use(webpackDevMiddleware(bundler, { noInfo: true }));
• app.use(webpackHotMiddleware(bundler, { log: console.log }));
• }
• ...
Hot Module Replacement

• Hot Module Replacement (HMR) exchanges, adds, or removes


modules while an application is running, without a full reload. This
can significantly speed up development in a few ways:
• Retain application state which is lost during a full reload.
• Save valuable development time by only updating what's changed.
• Instantly update the browser when modifications are made to
CSS/JS in the source code, which is almost comparable to changing
styles directly in the browser's dev tools.
How It Works

• In the Application
• The following steps allow modules to be swapped in and out of an
application:
1.The application asks the HMR runtime to check for updates.
2.The runtime asynchronously downloads the updates and notifies the
application.
3.The application then asks the runtime to apply the updates.
4.The runtime synchronously applies the updates.
• You can set up HMR so that this process happens automatically, or you
can choose to require user interaction for updates to occur.
How It Works

• In the Compiler
• In addition to normal assets, the compiler needs to emit an "update" to allow
updating from the previous version to the new version. The "update" consists of
two parts:
1.The updated manifest (JSON)
2.One or more updated chunks (JavaScript)
• The manifest contains the new compilation hash and a list of all updated chunks.
Each of these chunks contains the new code for all updated modules (or a flag
indicating that the module was removed).
• The compiler ensures that module IDs and chunk IDs are consistent between
these builds. It typically stores these IDs in memory (e.g. with
webpack-dev-server), but it's also possible to store them in a JSON file.
How It Works

• In a Module
• HMR is an opt-in feature that only affects modules containing HMR code. One example
would be patching styling through the style-loader. In order for patching to work, the
style-loader implements the HMR interface; when it receives an update through HMR, it
replaces the old styles with the new ones.

• Similarly, when implementing the HMR interface in a module, you can describe what
should happen when the module is updated. However, in most cases, it's not mandatory
to write HMR code in every module. If a module has no HMR handlers, the update
bubbles up. This means that a single handler can update a complete module tree. If a
single module from the tree is updated, the entire set of dependencies is reloaded.

• See the HMR API page for details on the module.hot interface.
How it Works
• In the Runtime
• Here things get a bit more technical... if you're not interested in the internals, feel free to jump to the HMR API page or HMR guide.

• For the module system runtime, additional code is emitted to track module parents and children. On the management side, the
runtime supports two methods: check and apply.

• A check makes an HTTP request to the update manifest. If this request fails, there is no update available. If it succeeds, the list of
updated chunks is compared to the list of currently loaded chunks. For each loaded chunk, the corresponding update chunk is
downloaded. All module updates are stored in the runtime. When all update chunks have been downloaded and are ready to be
applied, the runtime switches into the ready state.

• The apply method flags all updated modules as invalid. For each invalid module, there needs to be an update handler in the module
or in its parent(s). Otherwise, the invalid flag bubbles up and invalidates parent(s) as well. Each bubble continues until the app's entry
point or a module with an update handler is reached (whichever comes first). If it bubbles up from an entry point, the process fails.

• Afterwards, all invalid modules are disposed (via the dispose handler) and unloaded. The current hash is then updated and all accept
handlers are called. The runtime switches back to the idle state and everything continues as normal.
Serverside webpack &
Debugging
• Middle approach is somewhat challenge.
• Use some babel present comments in the command line depending
on node version.
• webpack.config.js: Add Source Map Configuration
devtool: 'source-map'
ESLINT
• A linter (something that lints) checks for suspicious code that may be
a bug. It can acheck whether your code adheres to conventions and
standards that you want to follow across your team to make the code
predictably readable.
• $ npm install --save-dev eslint-config-airbnb
. .eslintrc: Default .eslintrc File Contents
{
"extends": "airbnb"
}
ESLint Features
• SyStem Environment
• Syntax consistency(missing semicolon,paranthesis..)
• Editing conveniences(require curly braces after if statement)
• Structural Issues(variables should be defined before using)
• React Specifics
• Rules overrides
Unit -V
React Server Side Rendering
Server Side Rendering(SSR)
• Server−side rendering has been around for a while now. It was first
introduced in the early 2000s and has been used by many websites
since then.

• The idea behind this technique is to pre−render HTML pages on a server


and send them back to the client's browser as they request them.

• With server-side rendering (SSR), the page is rendered on the server.


This ensures that the page is available to users even before it loads on
their browser.
How SSR works?
• It is the process of rendering a webpage on the server before sending it to the
browser. So, when the server returns a ready-to-render HTML page and the
necessary JS scripts, all static elements are rendered immediately in the HTML.
• Meanwhile, the browser downloads and executes the JS code, which causes the
page to become interactive. The browser now handles the client-side interactions
on this page. The browser sends a request to the server via APIs for any new
content or data; only the newly required information is fetched.
• The advantages of this technique are that it saves time, reduces load time, and
increases SEO rankings because it provides a better user experience by showing
content faster than traditional client-side rendering does.
Overview of Server-side rendering in React

• Server-side rendering in React is possible using ReactDOMServer.renderToString method and then


returning the string from a Node.js HTTP server back to the browser.
• ReactDOMServer is used for server-side rendering, which means that it will render your components
onto an HTML string and send them back to the client as opposed to just returning them as an object
or array of objects.
• The renderToString method renders your whole application into a single HTML string, including any
data you need for initializing your app, like API responses or initial state variables, which is perfect
because you can use this string anywhere: on the server; in a static site generator; even in other
projects!
• Server-side rendering in React, in a nutshell, is the process by which the server converts web pages
into viewable layouts before transmitting them to the browser. Dynamic components can thus be
served as static HTML markup.
• When indexing does not correctly handle JavaScript, this approach may be helpful for search engine
optimization (SEO). It could also be useful when downloading a large JavaScript bundle hampered
by a slow network.
Parameters that derive Performance in
Server-Side Rendering
• When it comes to better performance using server-side rendering in React then, these
three significant parameters must be considered −
• TTFB (Time To First Byte) − the time that passes between clicking on the link and
receiving the first bit of content.
• FCP (First Contentful Paint) − the point at which the requested content is rendered.
• TTI (Time To Interactive) − the point at which the page becomes interactive.
• Because a completely rendered HTML page is transmitted to the browser, TTFB can be
higher, but FCP is significantly faster, improving performance and user−experience.
• The amount of scripts needed to render a web page and its complexity can both have an
impact on TTI. When rendered server− side, the majority of pages have a low TTI due to
their moderate amount of interactivity.
Setting up the Project

• npx create-react-app ssr-react-app


• cd ssr-react-app

• Adding Express Server


npm install express
Express Server Configuration
• Next, create a new folder called server at the root of your project and add a new file called
index.js. This file will contain the Express server configuration.

• // server/index.js
• const express = require('express');
• const app = express();
• const PORT = process.env.PORT || 3001;

• app.listen(PORT, () => {
• console.log(`Server is listening on port ${PORT}`);
• });
• In this code snippet, we create an Express app and start listening on port 3001.
Building React Components for SSR
• Now, let's create a simple React component to render on the server. In the src folder, create a new file called AppServer.js.
This component will be the server-rendered version of our application.

• // src/AppServer.js
• import React from 'react';
• const AppServer = () => {
• return (
• <div>
• <h1>Hello from Server-Side Rendered React App!</h1>
• </div>
• );
• };
Setting up Webpack for SSR

• To use server-side rendering, we need to bundle our React application


using Webpack. First, let's install the required dependencies:

• npm install webpack webpack-cli webpack-node-externals


@babel/core @babel/preset-env @babel/preset-react babel-loader --
save-dev
• Next, create a new file called webpack.server.js at the root of your
project. This file will contain the Webpack configuration for server-
side rendering.
• // webpack.server.js
• const path = require('path');
• const nodeExternals = require('webpack-node-externals');
• module.exports = {
• target: 'node',
• mode: 'development',
• externals: [nodeExternals()],
• entry: './server/index.js',
• output: {
• filename: 'server.js',
• path: path.resolve(__dirname, 'build'),
• },
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
],
},
},
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
},
};
In this configuration, we set the target to node and configure the input and output
paths. We also set up the Babel loader to transpile our JavaScript files, enabling
support for modern syntax and React components.

Now, add a new script to your package.json file to build the server-side bundle:

"scripts": {
...
"build:server": "webpack --config webpack.server.js"
}
Rendering the React Component on the Server

• With the Webpack configuration in place, it's time to render the React
component on the server. First, build the server-side bundle by
running the following command:

• npm run build:server


• This command generates a server.js file in the build folder.
Next, update the server/index.js file to render the AppServer
component:

// server/index.js
const express = require('express');
const React = require('react');
const ReactDOMServer = require('react-dom/server');
const AppServer = require('../src/AppServer').default;

const app = express();


const PORT = process.env.PORT || 3001;
app.get('/', (req, res) => {
const content =
ReactDOMServer.renderToString(<AppServer />);
const html = `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,
initial-scale=1.0" />
<title>React SSR</title>
</head>
<body>
<div id="root">${content}</div>
</body>
</html>
`;

res.send(html);
});

app.listen(PORT, () => {
console.log(`Server is listening on port ${PORT}`);
});
In this file, we import the AppServer component, use ReactDOMServer.renderToString() to convert it
into an HTML string, and send the generated HTML to the client.

Running the Application


Now that our server is set up, we can run the application. Add a new script to your package.json file
to start the server:

"scripts": {
...
"start:server": "node build/server.js"
}
To start the server, run the following command:

npm run start:server


Open your browser and navigate to http://localhost:3001. You should see the "Hello from Server-
Side Rendered React App!" message.

You might also like