Note: This is an article series on deploying web projects on AWS, including:
- Lightweight construction of backend Nest.js through Docker deployment of the entire web application service (1).
- Lightweight construction of frontend Next.js through Docker deployment of the entire web application service (2).
- Setting up an AWS EC2 server through Docker deployment of the entire web application service (3).
- Deploying frontend and backend services through Docker-compose in Docker deployment of the entire web application service (4).
- Distributing API routes and hosting Next.js static resources through Nginx in Docker deployment of the entire web application service (5).
- Automating CI/CD deployment through Git Action in Docker deployment of the entire web application service (6).
1、Introduce
As we all know, Nest.js by default only compiles TypeScript files instead of bundling all resources into bundles and chunks like in frontend projects. For example, to run the build command in the terminal: “npm run build”.
Comparing the compiled dist
directory with the source code, we can see that Nest.js simply converts TypeScript files to JavaScript.
The compiled JavaScript source code only contains your business logic. If you upload them to a server and try to run them, you will encounter errors because the JS business code does not include the @nestjs/xxx
related code.
This means that on the server, you still need to install the dependencies and devDependencies specified in your package.json
using pnpm i
or npm i
. However, installing dependencies with npm i
can be very disk-intensive. If your server has limited memory, you may encounter disk space issues during dependency installation. This is because the node_modules
folder contains a lot of unused code without tree-shaking from bundling tools like webpack
, turbopack
, or rollup
, leading to disk space waste.
The best practice for lightweight deployment is to use webpack
in your CI/CD
pipeline to bundle your code and then deploy only the bundle to the server.
2、How to implement this:
2.1、You can enable webpack bundling by modifying nest-cli.json
.
{
"compilerOptions": {
"deleteOutDir": true,
"webpack": true //enable webpack
}
}
After modifying nest-cli.json
and bundling again, although it has been bundled into a single bundle
(as shown in the screenshot below), the source code of @nestjs/core
and other dependencies is still not included in the bundle
. Instead, they are transformed into the commonjs
format used by Node.js. The bundling process only applies to your project’s business logic. In other words, this code still cannot be directly run on the server. You still need to run pnpm i
to install dependencies before you can run it.
2.2. Customize webpack.config.js to implement packaging
1、In order to address the issue mentioned above, which is the failure to include dependencies like @nestjs/core
in the bundle, we need to create a webpack.config.js
file in the root directory and utilize webpack.IgnorePlugin
to achieve this.
const path = require('path');
const webpack = require('webpack');
// Improving TypeScript build performance
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
// Note: These libraries do not need to be bundled into the bundle.
// Exclude them using `webpack.IgnorePlugin` as shown below.
const lazyImports = [
'@nestjs/microservices',
'@nestjs/microservices/microservices-module',
'@nestjs/websockets/socket-module',
'cache-manager',
'class-validator',
'class-transformer'
];
module.exports = {
entry: './src/main',
output: {
// output name
path: path.resolve(__dirname, 'nest-blog'),
// output filename
filename: 'main.js'
},
target: 'node',
// Setting it to empty will ignore the `webpack-node-externals` plugin.
externals: {},
// Handling TypeScript files
module: {
rules: [
{
test: /\.ts?$/,
use: {
loader: 'ts-loader',
options: { transpileOnly: true }
},
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.js', '.ts', '.json']
},
plugins: [
new webpack.IgnorePlugin({
checkResource(resource) {
if (!lazyImports.includes(resource)) {
return false;
}
try {
require.resolve(resource, {
paths: [process.cwd()]
});
} catch (err) {
return true;
}
return false;
}
}),
new ForkTsCheckerWebpackPlugin()
]
};
2、Then add a new script in package.json
to make Nest use the above webpack.config.js
configuration when building.
"scripts": {
"build:bundle": "NODE_ENV=production && nest build --webpack -- webpackPath=./webpack.config.js",
.....
},
3、Run pnpm build:bundle
again.
Finally, a bundle file nest-blog/main.js
will be generated. This main.js
no longer has dependencies like @nestjs/core
; all related dependencies are bundled into this main.js
. The remaining dependencies are Node.js native modules, so it can be directly run in a Node.js environment. Now you can simply upload this bundle to the server and run it without installing any dependencies.
4. Deployment
After uploading /nest-blog/main.js` to the server, you only need to run the following command in the terminal to start the Nest.js service.
shell
node ./nest-blog/main.js
5、Finally
Comparing with traditional deployment, Nest.js lightweight deployment only requires deploying a single bundle file. You don’t need to install a large number of dependencies using pnpm i
on the server. This approach saves disk space and is much more convenient.
Next Article: Lightweight construction of frontend Next.js through Docker deployment of the entire web application service (2).
Top comments (0)