我克隆了一个 Angular Universal 项目,用于服务器端渲染和路由,但每次我点击查看源代码页面时,都会出现以下错误,页面无法加载。(我正在以 FormData 的形式向 API 发送数据。)
每当我点击“查看源代码”页面时,控制台会显示此错误:
我的webpack.config.js文件如下:
每当我点击“查看源代码”页面时,控制台会显示此错误:
我使用 FormData 向服务器发送数据。错误 { Error: Uncaught (in promise): ReferenceError: FormData is not defined ReferenceError: FormData is not defined at BodyWisdomComponent.getAllBodyWisdom (webpack:///./dist-server/main.095f1696d45b5b44a263.js?:1:10104)
var myFormData = new FormData();
myFormData.append('timezone', 'asia/kolkata');
myFormData.append('page_no', this.pageNumber);
我的webpack.config.js文件如下:
const path = require('path');
const webpack = require('webpack');
const FormData = require('form-data');
var nodeExternals = require('webpack-node-externals');
/**
* This is a server config which should be merged on top of common config
*/
module.exports = {
entry: {
// This is our Express server for Dynamic universal
server: './server.ts',
// This is an example of Static prerendering (generative)
prerender: './prerender.ts'
},
resolve: { extensions: [".js", ".ts"] },
target: 'node',
externals: [/(node_modules|main\..*\.js)/],
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname),
filename: '[name].js'
},
mode: 'development',
node: {
__dirname: false
},
//externals: [/(node_modules|main\..*\.js)/],
/* externals: [nodeExternals({ whitelist: [/ngx-cookie/] })], */
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 文件如下:
const domino = require('domino');
const fs = require('fs');
const path = require('path');
const template = fs.readFileSync(path.join(__dirname, '.', 'dist', 'index.html')).toString();
const win = domino.createWindow(template);
const files = fs.readdirSync(`${process.cwd()}/dist-server`);
import fetch from 'node-fetch';
const FormData = require('form-data');
win.fetch = fetch;
global['window'] = win;
global['document'] = win.document;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true
};
},
});
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;
import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import { enableProdMode } from '@angular/core';
import * as express from 'express';
import * as compression from 'compression';
import * as cookieparser from 'cookie-parser';
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
const mainFiles = files.filter(file => file.startsWith('main'));
const hash = mainFiles[0].split('.')[1];
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(`./dist-server/main.${hash}`);
import { ngExpressEngine } from '@nguniversal/express-engine';
import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
const PORT = process.env.PORT || 4000;
import { ROUTES } from './static.paths';
enableProdMode();
const app = express();
app.use(compression());
app.use(cookieparser());
const redirectowww = false;
const redirectohttps = true;
const wwwredirecto = true;
app.use((req, res, next) => {
// for domain/index.html
if (req.url === '/index.html') {
res.redirect(301, 'https://' + req.hostname);
}
// check if it is a secure (https) request
// if not redirect to the equivalent https url
if (redirectohttps && req.headers['x-forwarded-proto'] !== 'https' && req.hostname !== 'localhost') {
// special for robots.txt
if (req.url === '/robots.txt') {
next();
return;
}
res.redirect(301, 'https://' + req.hostname + req.url);
}
// www or not
if (redirectowww && !req.hostname.startsWith('www.')) {
res.redirect(301, 'https://www.' + req.hostname + req.url);
}
// www or not
if (wwwredirecto && req.hostname.startsWith('www.')) {
const host = req.hostname.slice(4, req.hostname.length);
res.redirect(301, 'https://' + host + req.url);
}
next();
}
);
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', 'src');
app.get('*.*', express.static(path.join(__dirname, '.', 'dist')));
app.get(ROUTES, express.static(path.join(__dirname, '.', 'static')));
app.get('*', (req, res) => {
global['navigator'] = req['headers']['user-agent'];
const http = req.headers['x-forwarded-proto'] === undefined ? 'http' : req.headers['x-forwarded-proto'];
// tslint:disable-next-line:no-console
console.time(`GET: ${req.originalUrl}`);
res.render(
'../dist/index',
{
req: req,
res: res,
providers: [
{
provide: REQUEST, useValue: (req)
},
{
provide: RESPONSE, useValue: (res)
},
{
provide: 'ORIGIN_URL',
useValue: (`${http}://${req.headers.host}`)
}
]
},
(err, html) => {
if (!!err) { throw err; }
// tslint:disable-next-line:no-console
console.timeEnd(`GET: ${req.originalUrl}`);
res.send(html);
});
});
app.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}!`);
});
window.scroll
不是一个函数。你是不是想说window.onscroll
? - sjahannode.js
没有窗口。 - Keithdomino
进行服务器端渲染,所以我认为domino不支持window.scroll
,这也很合理,因为它是在服务器端渲染。 - Keith