使用 angular 7 通用 Openlayers 5
Using angular 7 universal with Openlayers 5
我有一个使用开放层 5.3 的 angular 7.2 应用程序。我正在尝试为此应用程序设置 angular 通用,但是当我 运行 通用服务器 (node dist/server.js
) 时,由于未定义仅客户端变量,我遇到了一些错误,例如作为 window
.
webpack:///./node_modules/ol/has.js?:54
var DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
^
ReferenceError: window is not defined
我尝试使用多米诺骨牌来模拟这些变量,但由于 canvas 元素
而失败并出现另一个错误
Error: NotYetImplemented
at HTMLCanvasElement.exports.nyi (/my/project/dist/server.js)
所有 OL 代码都被导入并在单个 MapComponent
组件中使用。我的导入在这个组件中看起来像这样:
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
我的主要问题是提到的错误会在我 运行 通用服务器时发生,所以甚至在尝试在浏览器中访问通用呈现的网站之前。
因此,当应用程序在 运行 客户端时,使用类似这样的方法仅实例化 MapComponent
是行不通的,因为崩溃发生在
之前
<app-map *ngIf="isBrowser"></app-map>
其中 isBrowser
变量在组件中初始化为 isPlatformmBrowser(platformId)
有什么建议吗?
这就是我在我的应用程序中控制 SSR 的方式,
我的组件端,
import { isPlatformBrowser } from '@angular/common';
import * as JQuery from "jquery";
constructor(
@Inject(PLATFORM_ID) public platformId){...}
ngOnInit() {
if (isPlatformBrowser(this.platformId)){
var $: any = jQuery; //for example, load jQuery if you are sure about platform is browser
}
}
例如,当 ssr 不是浏览器时,我正在显示加载栏。
我的模板端,
<ssr-loading *ngIf="platformId != 'browser'"></ssr-loading>
尝试使用Openlayer最新版本
"ol": "^5.3.1",
我遇到的错误是由 pixelworks
库引起的,它是 OL 5 的依赖项。
此库实例化一个 canvas 并尝试从中获取二维上下文,domino
不支持
var context = document.createElement('canvas').getContext('2d');
上下文不会立即使用,而是在始终实例化的地方创建。
由于我不想在服务器端执行代码时使用 OL,我的解决方案是在构建过程中修改 server.js
文件以删除此实例化。
sed -i "s/var context = document.createElement('canvas').getContext('2d');/var context = null;/" dist/server.js
注意:仍然需要domino
,因为从OL导出的模块也会尝试访问全局变量,例如window
添加到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`);
// const styleFiles = files.filter(file => file.startsWith('styles'));
// const hashStyle = styleFiles[0].split('.')[1];
// const style = fs.readFileSync(path.join(__dirname, '.', 'dist-server', `styles.${hashStyle}.bundle.css`)).toString();
global['window'] = win;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true
};
},
});
global['document'] = win.document;
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;
我有一个使用开放层 5.3 的 angular 7.2 应用程序。我正在尝试为此应用程序设置 angular 通用,但是当我 运行 通用服务器 (node dist/server.js
) 时,由于未定义仅客户端变量,我遇到了一些错误,例如作为 window
.
webpack:///./node_modules/ol/has.js?:54
var DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1;
^
ReferenceError: window is not defined
我尝试使用多米诺骨牌来模拟这些变量,但由于 canvas 元素
而失败并出现另一个错误Error: NotYetImplemented
at HTMLCanvasElement.exports.nyi (/my/project/dist/server.js)
所有 OL 代码都被导入并在单个 MapComponent
组件中使用。我的导入在这个组件中看起来像这样:
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
我的主要问题是提到的错误会在我 运行 通用服务器时发生,所以甚至在尝试在浏览器中访问通用呈现的网站之前。
因此,当应用程序在 运行 客户端时,使用类似这样的方法仅实例化 MapComponent
是行不通的,因为崩溃发生在
<app-map *ngIf="isBrowser"></app-map>
其中 isBrowser
变量在组件中初始化为 isPlatformmBrowser(platformId)
有什么建议吗?
这就是我在我的应用程序中控制 SSR 的方式,
我的组件端,
import { isPlatformBrowser } from '@angular/common';
import * as JQuery from "jquery";
constructor(
@Inject(PLATFORM_ID) public platformId){...}
ngOnInit() {
if (isPlatformBrowser(this.platformId)){
var $: any = jQuery; //for example, load jQuery if you are sure about platform is browser
}
}
例如,当 ssr 不是浏览器时,我正在显示加载栏。
我的模板端,
<ssr-loading *ngIf="platformId != 'browser'"></ssr-loading>
尝试使用Openlayer最新版本 "ol": "^5.3.1",
我遇到的错误是由 pixelworks
库引起的,它是 OL 5 的依赖项。
此库实例化一个 canvas 并尝试从中获取二维上下文,domino
var context = document.createElement('canvas').getContext('2d');
上下文不会立即使用,而是在始终实例化的地方创建。
由于我不想在服务器端执行代码时使用 OL,我的解决方案是在构建过程中修改 server.js
文件以删除此实例化。
sed -i "s/var context = document.createElement('canvas').getContext('2d');/var context = null;/" dist/server.js
注意:仍然需要domino
,因为从OL导出的模块也会尝试访问全局变量,例如window
添加到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`);
// const styleFiles = files.filter(file => file.startsWith('styles'));
// const hashStyle = styleFiles[0].split('.')[1];
// const style = fs.readFileSync(path.join(__dirname, '.', 'dist-server', `styles.${hashStyle}.bundle.css`)).toString();
global['window'] = win;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true
};
},
});
global['document'] = win.document;
global['CSS'] = null;
// global['XMLHttpRequest'] = require('xmlhttprequest').XMLHttpRequest;
global['Prism'] = null;