如何将 Angular 通用应用程序部署到 Node.js 生产服务器?
How to deploy Angular Universal app to Node.js production server?
我有一个带有 Universal 的 Angular 8 应用程序,我想将其部署到共享的 Web 主机生产服务器。我提前与虚拟主机核实,他们告诉我可以在他们的共享虚拟主机上托管 angular 通用网络应用程序。但是,无论我做什么,我都无法让网站正常工作。当我访问该网站时,我不断看到消息:"This site can't be reached"
到目前为止我完成的事情:
- 使用 npm 运行 build:ssr 构建项目,它创建了一个带有浏览器和服务器文件夹的 dist 文件夹以及一个 server.js 文件
- 将 dist 文件夹移动到 public_html 文件夹内的服务器。
然后通过 SSH 访问服务器并执行以下操作:
- 安装 Node.js 和 npm
- npm 安装
- npm 安装 pm2 -g
- pm2 启动 dist/server.js
pm2 启动没有问题。
这些是一些项目文件。如果有遗漏请询问,我会把它们添加到问题中。
部分 package.json 与脚本:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"build:client-and-server-bundles": "ng build --prod && ng run ProjectName:server:production --bundleDependencies all"
},
server.js 来自构建(只有表达部分,因为它有 25000 多行):
const app = express__WEBPACK_IMPORTED_MODULE_1__();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = __webpack_require__(144);
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express__WEBPACK_IMPORTED_MODULE_1__["static"](DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});
根据 SO 或其他地方的几个答案,您 "simply" 将 dist 文件夹复制粘贴到服务器,运行 pm2 并且您的网站应该可以正常工作。不过,我觉得要使其正常工作还有很多不足。
有人知道如何将 Angular 通用网站正确部署到生产服务器吗?
在server.ts
文件中更改
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
到
const DIST_FOLDER = join(process.cwd(), 'browser');
现在通过 npm run build:ssr
构建应用程序并将 dist
文件夹内的所有内容复制到您的 public 文件夹(在主机上)。请记住,您应该 运行 pm2 start server.js
.
而不是 pm2 start dist/server.js
我最终在我的 DirectAdmin 控制台中使用了一个名为 'NodeJS Selector' 的工具,因为 PM2 一直给我带来问题。它是一个用于安装应用程序、执行 npm install 和启动应用程序的工具。所以基本上你会使用 SSH 做什么,但是花哨 UI。设置如下所示:
我的文件夹结构如下所示:
domains
- appname.com
- public_html
- browser (=> this set as the document root in Apache, because index is located here)
- index.html
- .htaccess
- other files...
- server
- server.js
- package.json
我让虚拟主机做了两件事,因为我不是服务器上的根用户。他们将 documentroot 设置为 Apache 的 httpd.conf 文件中的浏览器文件夹。在同一个文件中,他们还向端口 4000 添加了 proxy 设置,因为那是我的应用 运行 所在的位置。所以在 httpd.conf 文件中将是这样的:
DocumentRoot "/domains/appname.com/public_html/browser"
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / https://localhost:4000/
ProxyPassReverse / https://localhost:4000/
接下来,在 NodeJS 选择器中,将根设置为启动文件所在的位置(在我的示例中为 server.js)。 package.json 也需要位于 public_html 文件夹中,这样您就可以在选择器中执行 npm install。
要启动应用程序,请单击 'Run JS script' 并选择 serve:ssr 选项,它会运行节点服务器命令。
Angular 文档描述了您必须如何在服务器上重写一些规则。 Apache 安装在我的网络服务器上,所以我添加了一个 .htaccess 文件,其中包含来自文档的重写规则。然而,此应用程序由 Node 提供服务,而 Node 可以提供实际路径。所以在我的例子中,我不必添加带有重写规则的 .htaccess 文件。相反,当我添加 .htaccess 文件时,它导致我的应用程序的通用端无法完全呈现。有关详细信息,请参阅 。
我有一个带有 Universal 的 Angular 8 应用程序,我想将其部署到共享的 Web 主机生产服务器。我提前与虚拟主机核实,他们告诉我可以在他们的共享虚拟主机上托管 angular 通用网络应用程序。但是,无论我做什么,我都无法让网站正常工作。当我访问该网站时,我不断看到消息:"This site can't be reached"
到目前为止我完成的事情:
- 使用 npm 运行 build:ssr 构建项目,它创建了一个带有浏览器和服务器文件夹的 dist 文件夹以及一个 server.js 文件
- 将 dist 文件夹移动到 public_html 文件夹内的服务器。 然后通过 SSH 访问服务器并执行以下操作:
- 安装 Node.js 和 npm
- npm 安装
- npm 安装 pm2 -g
- pm2 启动 dist/server.js
pm2 启动没有问题。
这些是一些项目文件。如果有遗漏请询问,我会把它们添加到问题中。
部分 package.json 与脚本:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"build:client-and-server-bundles": "ng build --prod && ng run ProjectName:server:production --bundleDependencies all"
},
server.js 来自构建(只有表达部分,因为它有 25000 多行):
const app = express__WEBPACK_IMPORTED_MODULE_1__();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = Object(path__WEBPACK_IMPORTED_MODULE_2__["join"])(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap } = __webpack_require__(144);
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express__WEBPACK_IMPORTED_MODULE_1__["static"](DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});
根据 SO 或其他地方的几个答案,您 "simply" 将 dist 文件夹复制粘贴到服务器,运行 pm2 并且您的网站应该可以正常工作。不过,我觉得要使其正常工作还有很多不足。
有人知道如何将 Angular 通用网站正确部署到生产服务器吗?
在server.ts
文件中更改
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
到
const DIST_FOLDER = join(process.cwd(), 'browser');
现在通过 npm run build:ssr
构建应用程序并将 dist
文件夹内的所有内容复制到您的 public 文件夹(在主机上)。请记住,您应该 运行 pm2 start server.js
.
pm2 start dist/server.js
我最终在我的 DirectAdmin 控制台中使用了一个名为 'NodeJS Selector' 的工具,因为 PM2 一直给我带来问题。它是一个用于安装应用程序、执行 npm install 和启动应用程序的工具。所以基本上你会使用 SSH 做什么,但是花哨 UI。设置如下所示:
我的文件夹结构如下所示:
domains
- appname.com
- public_html
- browser (=> this set as the document root in Apache, because index is located here)
- index.html
- .htaccess
- other files...
- server
- server.js
- package.json
我让虚拟主机做了两件事,因为我不是服务器上的根用户。他们将 documentroot 设置为 Apache 的 httpd.conf 文件中的浏览器文件夹。在同一个文件中,他们还向端口 4000 添加了 proxy 设置,因为那是我的应用 运行 所在的位置。所以在 httpd.conf 文件中将是这样的:
DocumentRoot "/domains/appname.com/public_html/browser"
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / https://localhost:4000/
ProxyPassReverse / https://localhost:4000/
接下来,在 NodeJS 选择器中,将根设置为启动文件所在的位置(在我的示例中为 server.js)。 package.json 也需要位于 public_html 文件夹中,这样您就可以在选择器中执行 npm install。
要启动应用程序,请单击 'Run JS script' 并选择 serve:ssr 选项,它会运行节点服务器命令。
Angular 文档描述了您必须如何在服务器上重写一些规则。 Apache 安装在我的网络服务器上,所以我添加了一个 .htaccess 文件,其中包含来自文档的重写规则。然而,此应用程序由 Node 提供服务,而 Node 可以提供实际路径。所以在我的例子中,我不必添加带有重写规则的 .htaccess 文件。相反,当我添加 .htaccess 文件时,它导致我的应用程序的通用端无法完全呈现。有关详细信息,请参阅