Reputation: 66
I'm working on an angular projet,
versions:
-Angular CLI: 8.3.29
-Node: 12.14.1
-Angular: 8.2.14
I need to apply side rendering on it, I used the following command to set up angular univeral on my project
npm install @nguniversal/express-engine --save
After solving lot of problems (building, flickering, double loading page...) I now can launch it on my local environment with
build:ssr && serve:ssr
But when i try do deploy it on a production server, after building the project on the production server when I try to start the server with node /dist/server/main.js
I got the following error
Error: Cannot find module 'zone.js/dist/zone-node'
I searched on forums and I found that I've to build my server side code with webpack
so I update my package.json to
"dev:ssr": "ng run my-app-name:serve-ssr",
"serve:ssr": "node dist/server.js",
"build:client-and-server-bundles": "ng build --prod && ng run my-app-name:server:production",
"build-wp:ssr": "npm run build:client-and-server-bundles && npm run webpack:server",
"webpack:server": "webpack --config webpack.server.config.js --progress --colors"
webpack.server.config.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'none',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts'
},
externals: {
'./dist/server/main': 'require("./server/main")'
},
target: 'node',
resolve: { extensions: ['.ts', '.js'] },
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
noParse: /polyfills-.*\.js/,
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `@angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true },
},
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};
server.ts
import 'zone.js/dist/zone-node';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
// The Express app is exported so that it can be used by serverless Functions.
export function app(): express.Express {
const server = express();
const distFolder = join(process.cwd(), 'dist/browser');
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
const DIST_FOLDER = join(process.cwd(), 'dist');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
server.set('view engine', 'html');
server.set('views', join(DIST_FOLDER, 'browser'));
//server.set('views', distFolder);
// Example Express Rest API endpoints
// server.get('/api/**', (req, res) => { });
// Serve static files from /browser
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
function run(): void {
const port = process.env.PORT || 4200;
// Start up the Node server
const server = app();
server.listen(port, () => {
console.log(`Node Express server listening on http://localhost:${port}`);
});
}
// Webpack will replace 'require' with '__webpack_require__'
// '__non_webpack_require__' is a proxy to Node 'require'
// The below code is to ensure that the server is run only when not requiring the bundle.
declare const __non_webpack_require__: NodeRequire;
const mainModule = __non_webpack_require__.main;
const moduleFilename = mainModule && mainModule.filename || '';
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
run();
}
export * from './src/main.server';
angular.json
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"my-app-name": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"styleext": "scss"
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/assets/sass/main.scss",
"node_modules/bootstrap/scss/bootstrap.scss"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "my-app-name:build",
"sslKey": "ssl/server.key",
"sslCert": "ssl/server.crt"
},
"configurations": {
"production": {
"browserTarget": "my-app-name:build:production"
}
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "server.ts",
"tsConfig": "src/tsconfig.server.json"
},
"configurations": {
"production": {
"outputHashing": "media",
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"sourceMap": false,
"optimization": {
"scripts": false,
"styles": true
}
}
}
},
"serve-ssr": {
"builder": "@nguniversal/builders:ssr-dev-server",
"options": {
"browserTarget": "my-app-name:build",
"serverTarget": "my-app-name:server"
},
"configurations": {
"production": {
"browserTarget": "my-app-name:build:production",
"serverTarget": "my-app-name:server:production"
}
}
},
"prerender": {
"builder": "@nguniversal/builders:prerender",
"options": {
"browserTarget": "my-app-name:build:production",
"serverTarget": "my-app-name:server:production",
"routes": [
"/"
]
},
"configurations": {
"production": {}
}
}
}
},
},
"defaultProject": "my-app-name"
}
Now when i play the command
webpack:server
I got tons of error like this one :
ERROR in ./src/app/components/auth/login/login.component.ts Module not found: Error: Can't resolve 'src/app/web-services/facebook-sdk.service' in 'C:\Code\my-app-name\src\app\components\auth\login' @ ./src/app/components/auth/login/login.component.ts 21:0-79 140:8-26 @ ./src/app/components/auth/login/login.module.ts @ ./src/app/app-routing.module.ts @ ./src/app/app.module.ts @ ./src/app/app.server.module.ts @ ./src/main.server.ts @ ./server.ts
I don't know how to find where is the problems, is it a path which is have a bad value somewhere in my config ?
I checked for hours but i cant find the error.
please help me !!!!
Thank u in advance
Alex
Upvotes: 0
Views: 1967
Reputation: 66
I found the problem:
In my components and in my modules I used imports with the relative paths
import { ApiClientService } from 'src/app/web-services/api-client.service';
I changed it to absolute paths
import { ApiClientService } from '../../web-services/api-client.service';
Build is Ok now
Upvotes: 1