将我的Angular 8项目升级到9之后,我的所有东西都被升级到了最新版本,出现了几个问题。
1.- webpack.config.js
文件已更名为 .bak ,因此似乎不再使用 webpack 了。实际上,如果我尝试重新激活 webpack 构建,什么也不会发生,它会创建构建,但脚本不会运行。使用 node server.js
运行时没有任何提示。
2.- 现在 dist 文件夹中没有根目录下的 .js 文件,浏览器和服务器构建的文件夹与以前一样,但即使编辑 web.config
文件以指示 iisnode 运行 server/main.js
而不是 server.js
,无论我做什么都会抛出500错误。
3.- 唯一起作用的是在本地运行。
npm run dev:ssr
这意味着浏览器构建中对视图的引用已经存在,但它会像从根目录请求dist/browser一样运行。
我在angular.json
中修改了构建路径和服务器构建路径,以便在./dist文件夹的根目录中创建main.js文件。
angular.json(outputPath已被修改)
architect: {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.ts",
"tsConfig": "tsconfig.app.json",
...
},
...
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist",
"main": "server.ts",
"tsConfig": "tsconfig.server.json"
},
...
},
...
}
好的,问题来了。浏览器生成构建文件夹 ./dist/browser 没有问题,服务器生成构建文件夹 ./dist 并将 main.js 文件直接放入其中,但不知何故它决定删除 ./dist/browser 文件夹,当运行 node main.js (web.config 指向 main.js)时,它无法找到 ./browser/index.html,当然这是因为服务器构建过程成功删除了 browser 文件夹。
一个临时的解决方案是再运行一次第三个构建(即浏览器构建)。
我希望这个问题能够得到解决,但说实话,这并不会对我造成困扰,因为是计算机运行构建,而不是我,但是你知道,如果服务器构建过程不删除浏览器构建文件夹,那么这样做可能会更好、更快。
现在,每次我部署所选的构建时,它都会直接从 AppVeyor 部署到 Azure 应用服务,没有任何问题。
package.json(请注意,在服务器构建之后还有额外的生产构建)。
{
...
"scripts": {
...
"dev:ssr": "ng run Angular-Universal:serve-ssr",
"serve:ssr": "node dist/main.js",
"build:ssr": "npm run build:universal && ng run Angular-Universal:build:production",
"start:ssr": "npm run build:ssr && npm run serve:ssr",
"build:universal": "ng run Angular-Universal:build:production && ng run Angular-Universal:server:production",
"prerender": "ng run Angular-Universal:prerender"
},
...
}
请注意,
build:ssr
脚本执行了两次构建,然后再进行浏览器构建。
还要注意,
serve:ssr
脚本已被修改为运行
dist/main.js
最后,必须修改server.ts文件,以请求从./browser/index.html或./dist/browser/index.html获取视图,具体取决于目标系统的文件夹结构。当部署到Azure应用服务时,main.js请求browser/index.html,但如果在macOS上运行
npm run dev:ssr
或
node main.js
的本地环境中提供项目,则请求dist/browser/index.html。无论如何,一个简单的if语句都可以解决这个问题。
server.ts(对app函数的更改)
export function app() {
const server = express();
let distFolder: string;
const path1 = join(process.cwd(), 'browser');
const path2 = join(process.cwd(), 'dist/browser');
if (fs.existsSync(path1)) {
distFolder = path1;
} else if (fs.existsSync(path2)) {
distFolder = path2;
} else {
return null;
}
console.log('distFolder:', distFolder);
const indexHtml = fs.existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
server.engine('html', ngExpressEngine({
bootstrap: AppServerModule,
}));
server.set('view engine', 'html');
server.set('views', distFolder);
server.get('*.*', express.static(distFolder, {
maxAge: '1y'
}));
server.get('*', (req, res) => {
res.render(indexHtml, { req, providers: [{ provide: APP_BASE_HREF, useValue: req.baseUrl }] });
});
return server;
}
如果您想知道将 web.config
文件复制到 dist
文件夹的根目录会发生什么,那么由于我正在使用 AppVeyor 进行 CI/CD,我已经修改了构建命令以包括 web.config
(直接从源代码文件中放入 .7z 文件)。
为什么不包含我的 web.config
呢?
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime enableVersionHeader="false" />
</system.web>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Strict-Transport-Security" value="max-age=31536000"/>
<add name="X-Content-Type-Options" value="nosniff" />
<add name="X-Frame-Options" value="DENY" />
<add name="X-XSS-Protection" value="1; mode=block" />
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
<webSocket enabled="false" />
<handlers>
<add name="iisnode" path="main.js" verb="*" modules="iisnode"/>
</handlers>
<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Permanent" />
</rule>
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
<match url="^main.js\/debug[\/]?" />
</rule>
<rule name="DynamicContent">
<match url="^(?!.*login).*$"></match>
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true"/>
</conditions>
<action type="Rewrite" url="main.js"/>
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security" pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
</outboundRules>
</rewrite>
<security>
<requestFiltering>
<hiddenSegments>
<remove segment="bin"/>
</hiddenSegments>
</requestFiltering>
</security>
<httpErrors existingResponse="PassThrough" />
<iisnode watchedFiles="web.config;*.js;browser/*.*" />
</system.webServer>
</configuration>
我希望这篇文章能够帮助到其他人,或者至少对于讨论有所用处。没有人喜欢在升级到9版本后尝试进行Azure应用服务的成功部署时遇到问题。如果有什么可以改进的地方,请告诉我,也许可以通过构建参数来避免浏览器构建文件夹被删除等问题。干杯。