预渲染 es6 错误 Angular 2/Typescript/Webpack
Prerender es6 Errors with Angular 2/Typescript/Webpack
我正在尝试使用预呈现节点和私有预呈现服务器来预呈现 Angular2/Express 应用程序。如果我尝试在 tsconfig.json 中以 es5 为目标,预渲染服务器会抛出此错误:
ReferenceError: Can't find variable: Map
undefined:1521 in KeyRegistry
:1540
:7
如果我尝试以 es6 为目标(包括 files
数组中的 node_modules/typescript/lib/lib.es6.d.ts
),预呈现服务器会抛出此错误:
SyntaxError: Unexpected token 'const'
http://localhost:3000/app.js:50 in eval
http://localhost:3000/app.js:50
http://localhost:3000/app.js:20 in __webpack_require__
http://localhost:3000/app.js:40
我想我需要包含某种 polyfill 才能使其正常工作,但我不知道要包含什么或在哪里包含它。
这是我的 webpack 配置以防万一:
var webpack = require('webpack');
var path = require('path');
var rootDir = path.resolve();
module.exports =
{
target: 'node',
entry: rootDir + "/dist/client/app/bootstrap.js",
output: {
path: rootDir + "/dist/client", publicPath: '/', filename: "app.js",
pathinfo: true
},
devtool: 'eval',
resolve: {
root: rootDir + "/dist/client/app",
extensions: ['', '.js']
},
module: {
loaders: [
{
test: /\.ts/, loaders: ['ts-loader'], exclude: /node_modules/
}
]
}
};
我的客户端 tsconfig 以防万一:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": false,
"outDir": "../../dist/client",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true
},
"files": ["app/bootstrap.ts", "app/vendor.ts", "app/Window.ts", "tests/index.ts", "../../node_modules/typescript/lib/lib.es6.d.ts"]
}
更新
如果我将我的 webpack 配置更改为目标 web
而不是 node
,并在预渲染服务器中注释掉 server.use(prerender.removeScriptTags());
,则请求每次都会到达预渲染服务器并且没有错误被抛出,但也没有任何预渲染。不过,似乎比以前更近了,所以我想我会更新。
更新
Prerender 似乎不执行任何 Angular 代码。如果我在 index.html 头部的脚本标记中设置 window.prerenderReady = false
,然后在实例化我的根组件时再次尝试将其设置为 true,则预呈现服务器超时:
import { Component, OnInit } from '@angular/core'
@Component({
selector: 'my-app',
template: `
<div id="main"> all the things </div>
`
})
export class AppComponent implements OnInit
{
constructor(){}
ngOnInit()
{
// Prerender never executes this code before it times out
window.prerenderReady = true;
console.info('Prerender Ready');
}
}
我设法通过以下更改使其正常工作:
在 Webpack 配置中使用 target: 'web'
。
使用 target: 'es5'
并将 node_modules/typescript/lib/lib.es6.d.ts
添加到 tsconfig.json 中的文件数组。这可以防止 es6 东西的编译时错误。
显然,尽管针对 web 和 es5,Webpack 仍然保留了 es6 语法,而 PhantomJs 无法处理。我不喜欢在 Typescript 项目中包含 babel 的想法,但这是我发现的唯一可行的方法:require('babel-polyfill');
在任何可能使用任何 es6 语法的应用程序代码或供应商代码之前。
在文档的head
中设置window.prerenderReady = false;
,然后在实例化根应用程序组件时设置为true
:
export class ApplicationComponent implements OnInit
{
ngOnInit()
{
window.prerenderReady = true;
}
}
注意:要使上述内容在 Typescript 中工作,您需要确保 属性 prerenderReady
存在于类型 Window 上。例如:
interface Window
{
prerenderReady:boolean;
}
在服务器端,确保在配置任何路由之前配置预呈现节点。例如:
export function routeConfig(app:express.Application):void
{
// Prerender
app.use(require('prerender-node').set('prerenderServiceUrl', CONFIG.prerenderServiceUrl));
// Angular routes should return index.html
app.route(CONFIG.angularRoutes)
.get((req:Request, res:Response, next:NextFunction) =>
{
return res.sendFile(`${app.get('appPath')}/client/index.html`);
});
}
希望这对某人有所帮助:)
我正在尝试使用预呈现节点和私有预呈现服务器来预呈现 Angular2/Express 应用程序。如果我尝试在 tsconfig.json 中以 es5 为目标,预渲染服务器会抛出此错误:
ReferenceError: Can't find variable: Map
undefined:1521 in KeyRegistry
:1540
:7
如果我尝试以 es6 为目标(包括 files
数组中的 node_modules/typescript/lib/lib.es6.d.ts
),预呈现服务器会抛出此错误:
SyntaxError: Unexpected token 'const'
http://localhost:3000/app.js:50 in eval
http://localhost:3000/app.js:50
http://localhost:3000/app.js:20 in __webpack_require__
http://localhost:3000/app.js:40
我想我需要包含某种 polyfill 才能使其正常工作,但我不知道要包含什么或在哪里包含它。
这是我的 webpack 配置以防万一:
var webpack = require('webpack');
var path = require('path');
var rootDir = path.resolve();
module.exports =
{
target: 'node',
entry: rootDir + "/dist/client/app/bootstrap.js",
output: {
path: rootDir + "/dist/client", publicPath: '/', filename: "app.js",
pathinfo: true
},
devtool: 'eval',
resolve: {
root: rootDir + "/dist/client/app",
extensions: ['', '.js']
},
module: {
loaders: [
{
test: /\.ts/, loaders: ['ts-loader'], exclude: /node_modules/
}
]
}
};
我的客户端 tsconfig 以防万一:
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": false,
"outDir": "../../dist/client",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": true
},
"files": ["app/bootstrap.ts", "app/vendor.ts", "app/Window.ts", "tests/index.ts", "../../node_modules/typescript/lib/lib.es6.d.ts"]
}
更新
如果我将我的 webpack 配置更改为目标 web
而不是 node
,并在预渲染服务器中注释掉 server.use(prerender.removeScriptTags());
,则请求每次都会到达预渲染服务器并且没有错误被抛出,但也没有任何预渲染。不过,似乎比以前更近了,所以我想我会更新。
更新
Prerender 似乎不执行任何 Angular 代码。如果我在 index.html 头部的脚本标记中设置 window.prerenderReady = false
,然后在实例化我的根组件时再次尝试将其设置为 true,则预呈现服务器超时:
import { Component, OnInit } from '@angular/core'
@Component({
selector: 'my-app',
template: `
<div id="main"> all the things </div>
`
})
export class AppComponent implements OnInit
{
constructor(){}
ngOnInit()
{
// Prerender never executes this code before it times out
window.prerenderReady = true;
console.info('Prerender Ready');
}
}
我设法通过以下更改使其正常工作:
在 Webpack 配置中使用 target: 'web'
。
使用 target: 'es5'
并将 node_modules/typescript/lib/lib.es6.d.ts
添加到 tsconfig.json 中的文件数组。这可以防止 es6 东西的编译时错误。
显然,尽管针对 web 和 es5,Webpack 仍然保留了 es6 语法,而 PhantomJs 无法处理。我不喜欢在 Typescript 项目中包含 babel 的想法,但这是我发现的唯一可行的方法:require('babel-polyfill');
在任何可能使用任何 es6 语法的应用程序代码或供应商代码之前。
在文档的head
中设置window.prerenderReady = false;
,然后在实例化根应用程序组件时设置为true
:
export class ApplicationComponent implements OnInit
{
ngOnInit()
{
window.prerenderReady = true;
}
}
注意:要使上述内容在 Typescript 中工作,您需要确保 属性 prerenderReady
存在于类型 Window 上。例如:
interface Window
{
prerenderReady:boolean;
}
在服务器端,确保在配置任何路由之前配置预呈现节点。例如:
export function routeConfig(app:express.Application):void
{
// Prerender
app.use(require('prerender-node').set('prerenderServiceUrl', CONFIG.prerenderServiceUrl));
// Angular routes should return index.html
app.route(CONFIG.angularRoutes)
.get((req:Request, res:Response, next:NextFunction) =>
{
return res.sendFile(`${app.get('appPath')}/client/index.html`);
});
}
希望这对某人有所帮助:)