Ng-lazyload-image: Angular Universal 构建预渲染错误

创建于 2019-01-08  ·  23评论  ·  资料来源: tjoskar/ng-lazyload-image

  • 我正在提交一个...

    • [x] 错误报告
    • [ ] 功能要求
    • [ ] 支持请求
  • 您要请求功能还是报告错误
    您的库和 Angular Universal 构建预渲染功能存在错误

  • 目前的行为是什么?
    运行命令时:
    npm run build:prerender

它运行:
"generate:prerender": "cd dist && node prerender",

然后失败并出现错误:
```/node_modules/ng-lazyload-image/src/lazyload-image.module.js:1
(function (exports, require, module, __filename, __dirname) { import { NgModule } from '@angular/core';
^^^^^^

语法错误:意外的令牌导入
在 createScript (vm.js:80:10)
在 Object.runInThisContext (vm.js:139:10)
在 Module._compile (module.js:617:28)
在 Object.Module._extensions..js (module.js:664:10)
在 Module.load (module.js:566:32)
在 tryModuleLoad (module.js:506:12)
在 Function.Module._load (module.js:498:3)
在 Module.require (module.js:597:17)
在要求(内部/module.js:11:18)
在 Object.ng-lazyload-image/src/lazyload-image.module (/dist/server/main.js:1350:18)


* **provide the steps to reproduce**
1) Duplicate the Angular Universal starter project from:
https://github.com/angular/universal-starter

2) Add your library, following install instructions:
https://github.com/tjoskar/ng-lazyload-image

3) Run the Angular build command to see the error:
```npm run build:prerender```

* **What is the expected behavior?**
No error, and to continue building.

* **What is the motivation / use case for changing the behavior?**
Otherwise your plugin cannot be used with Angular Universal, which means no static site generation :(

* **Please tell us about your environment:**
  - MacOS 10.13.6
  - node 8.9.1
  - ng-cli 6.0.0 and tested with 7.1.4
  - angular 6.0.0 and tested with 7.1.4
  - nguniversal 6.0.0 and tested with 7.0.2

* **Other information**

Looks like other people have had similar problems with Angular Universal and third-party libraries such as yours:
https://github.com/angular/angular-cli/issues/7200#issuecomment-329711848

They say the third-party libraries aren't being built correctly, which means Angular Universal fails:
https://github.com/angular/angular-cli/issues/7200#issuecomment-328991769

for example they suggest adding to your package.json
```"main": "./bundles/quickstart-lib.umd.js",
"module": "./quickstart-lib.es5.js",
"es2015": "./quickstart-lib.js",
"typings": "./quickstart-lib.d.ts",

方法一
修补您的插件根目录:
npm install @babel/cli @babel/core @babel/preset-env @babel/plugin-transform-modules-umd

在插件文件夹的根目录中添加一个 .babelrc 文件:

{
  "plugins": [["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }]],
  "presets": ["@babel/preset-env"]
}

更新你的插件 package.json

"main": "./lib-umd/index.js",
"module": "./lib-es5/index.js",
"es2015": "./lib/index.js",
"typings": "./lib/index.d.ts",
"scripts": {
  "build:umd": "babel ./lib/*.js --out-dir ./lib-umd --plugins @babel/plugin-transform-modules-umd",
  "build:es5": "babel ./lib/*.js --out-dir ./lib-es5"
}

然后运行构建:
npm run build:es5 && npm run build:umd

并添加到我自己的项目 tsconfig.json

"compilerOptions": {
  "paths": { "@angular/*": ["../node_modules/@angular/*"] },
}

但是仍然遇到与 Angular Universal 相同的错误:(

方法二
在示例项目中使用 Typescript 构建选项:
https://github.com/filipesilva/angular-quickstart-lib

最有用的评论

我在尝试使用 angular Universal 构建时遇到了同样的问题。 @tjoskar您是否考虑过使用ng-packagr来构建您的库? 您可以以 FESM2015、FESM5 和 UMD 格式构建和捆绑您的库。
在这里查看: https :

所有23条评论

我也遇到了同样的错误,我安装了 angular Universal

``` node_modules\ng-lazyload-image\index.js:1
(功能(出口,要求,模块,__filename,__dirname){ import { LazyLoadImageDirective } from './src/lazyload-image.directive';
^^^^^^

语法错误:意外的令牌导入
在 createScript (vm.js:80:10)
在 Object.runInThisContext (vm.js:139:10)
在 Module._compile (module.js:617:28)
在 Object.Module._extensions..js (module.js:664:10)
在 Module.load (module.js:566:32)
在 tryModuleLoad (module.js:506:12)
在 Function.Module._load (module.js:498:3)
在 Module.require (module.js:597:17)
在要求(内部/module.js:11:18)
在 eval (webpack:///external_%22ng-lazyload-image%22?:1:18) ```

我最终编写了自己的指令,该指令适用于 Universal:

import { Directive, ElementRef, Inject, Input, OnInit, PLATFORM_ID} from '@angular/core';
import { isPlatformBrowser } from '@angular/common';

@Directive({
  selector: '[appLazyLoadImage]'
})
export class LazyLoadImageDirective implements OnInit {
  @Input() srcLazy: string;

  constructor(
    private el: ElementRef,
    @Inject(PLATFORM_ID) private platformId: Object,
  ) { }

  ngOnInit() {
    // only run lazy image loading in the browser
    if (isPlatformBrowser(this.platformId)) {
      // if browser supports IntersectionObserver
      if ('IntersectionObserver' in window) {
        const lazyImageObserver = new IntersectionObserver((entries, observer) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              entry.target.setAttribute('src', this.srcLazy);
              entry.target.classList.add('lazy-loaded');
              lazyImageObserver.unobserve(entry.target);
            }
          });
        });
        lazyImageObserver.observe(this.el.nativeElement);
      } else {
        // Otherwise replace image by default
        this.el.nativeElement.setAttribute('src', this.srcLazy);
      }
    }
  }

}

将其导入您的模块:

import { LazyLoadImageDirective } from './lazy-load-image.directive';
...
@NgModule({
  imports: [
    CommonModule
  ],
  declarations: [
    LazyLoadImageDirective
  ],
  exports: [
    CommonModule,
    LazyLoadImageDirective
  ]
})
...etc

并在图像上使用:
<img src="../assets/placeholder.jpg" srcLazy="../assets/myimage.jpg" alt="Example" appLazyLoadImage />

我也遇到了同样的错误,我安装了 angular Universal

(function (exports, require, module, __filename, __dirname) { import { LazyLoadImageDirective } from './src/lazyload-image.directive';
                                                              ^^^^^^

SyntaxError: Unexpected token import
    at createScript (vm.js:80:10)
    at Object.runInThisContext (vm.js:139:10)
    at Module._compile (module.js:617:28)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
    at tryModuleLoad (module.js:506:12)
    at Function.Module._load (module.js:498:3)
    at Module.require (module.js:597:17)
    at require (internal/module.js:11:18)
    at eval (webpack:///external_%22ng-lazyload-image%22?:1:18) ```

使用这个

在 webpack 配置中添加了这个

externals: [ nodeExternals({ whitelist: [ /^ng-lazyload-image/, ] })

我猜angular universal只能导入 ComonJS 模块,因为ng-lazyload-image只有 ES 模块作为目标angular universal失败。

我想我们必须为ng-lazyload-image设置多个目标,正如@kmturley所描述的那样。 但这也意味着摇树将不起作用。

@xmasuku ,你能给出一个更详细的 webpack 配置示例吗? 你在哪里使用whitelist

@tjoskar我使用了我的自定义 webpack 构建,我没有使用 angular cli

我已经生成了一个 cli 项目,但我得到了同样的错误

好的,我今晚试试看

我在尝试使用 angular Universal 构建时遇到了同样的问题。 @tjoskar您是否考虑过使用ng-packagr来构建您的库? 您可以以 FESM2015、FESM5 和 UMD 格式构建和捆绑您的库。
在这里查看: https :

// 看起来它是通用的常见问题,例如。 https://github.com/angular/angular-cli/issues/7200
// 我的项目中有这个设置
// 替换: --- " compile:server ": "tsc -p server.tsconfig.json"
// 用这个: --- " compile:server ": "node --max_old_space_size=3072 node_modules/webpack/bin/webpack.js --config webpack.server.config.js --progress --colors"

// 然后创建 webpack.server.config.js 添加如下代码:

const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');

module.exports = {
  mode: 'none',
  entry: {
    // This is our Express server for Dynamic universal
    server: './server.ts'
  },
  target: 'node',
  resolve: { extensions: ['.ts', '.js'] },
  externals: [ nodeExternals({
    whitelist: [
        /^ng-lazyload-image/,
    ]
  }), /.*?webpack.*?/i ],
  optimization: {
    minimize: false
  },
  output: {
    // Puts the output at the root of the dist folder
    path: path.join(__dirname, 'dist'),
    filename: '[name].js'
  },
  module: {
    rules: [
      { test: /\.ts$/, loader: 'ts-loader' },
      {
        // Mark files inside `@angular/core` as using SystemJS style dynamic imports.
        // Removing this will cause deprecation warnings to appear.
        test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
        parser: { system: true },
      },
    ]
  },
  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

``
导入 'zone.js/dist/zone-node';
从“@angular/core”导入{enableProdMode};
// 快速引擎
从“@nguniversal/express-engine”导入 {ngExpressEngine};
// 为延迟加载导入模块映射
从'@nguniversal/module-map-ngfactory-loader'导入{provideModuleMap};

import * as express from 'express';
从“路径”导入 {join};

// 使用 Prod 模式更快的服务器渲染(从不需要开发模式)
enableProdMode();

// 快速服务器
const app = express();

const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');

// * 注意 :: 将此保留为 require() 因为此文件是从 webpack 动态构建的
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');

// 我们的通用 express-engine(找到 @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
引导程序:AppServerModuleNgFactory,
供应商: [
提供模块映射(LAZY_MODULE_MAP)
]
}));

app.set('视图引擎', 'html');
app.set('views', DIST_FOLDER);

// 示例 Express Rest API 端点
// app.get('/api/ *', (req, res) => { });// 从 /browser 提供静态文件app.get(' .*', express.static(DIST_FOLDER, {
最大年龄:'1y'
}));

// 所有常规路线都使用通用引擎
app.get('*', (req, res) => {
res.render('index', { req });
});

// 启动节点服务器
app.listen(PORT, () => {
console.log( Node Express server listening on http://localhost:${PORT} );
});

现在,应该有效。

@tjoskar我使用了你的分支,它似乎解决了构建错误的问题。 你有什么打算合并和发布的计划吗?

@Loutrinos ,抱歉耽搁了。 您能否尝试安装[email protected] (测试版)以查看是否可以解决问题。 谢谢。

@tjoskar我在 5.1.0 版本中看到结构不同。 这暂时没问题,因为它是测试版。
有了5.1.0 Angular Universal 就不会再坏了 :P

@Loutrinos

我在 5.1.0 版本中看到结构不同

抱歉,我创建了一个与以前结构相同的新版本 ([email protected])。 我前几周一直很忙,但现在我又开始工作了,所以让我知道它对你有什么作用。

安装 5.1.1 版本后,我收到此错误:
ReferenceError: IntersectionObserver is not defined

@agustintarifa你的tsconfig.json文件是什么样的?

我刚刚创建了这个 repo: https : https://github.com/angular/universal-starter ,安装了ng-lazyload-image (npm install [email protected]),添加了一个图像,用npm run build:prerender和编译然后启动服务器: node dist/server.js

感谢您的回答@tjoskar
它现在工作了,我改变了我的模块。
在 app.module 中使用: LazyLoadImageModule.forRoot({}),
在其他模块中: LazyLoadImageModule.forRoot({ preset: intersectionObserverPreset, }),

唯一的问题,偏移量在顶部不起作用以查看第一张图像我至少需要滚动 1px,然后在可见时加载另一个图像,我想在 200px 之前加载图像

嗯.. 在我上面的例子中,我只在app.module声明了LazyLoadImageModule app.module并且它工作正常,我无法真正重现错误。 如果有人可以创建一个小的 repo 来重现错误(或提供分步说明),那将非常有帮助。

@agustintarifa ,关于偏移问题。 你能为此创建一个新问题吗?

嗨,我们什么时候可以期待 v5.1.1 成为稳定版而非 Beta 版? 因为我的 SSR 也有这个问题。

@vytautas-pranskunas-,我将在明天发布一些其他较小的修复程序。

声优👍

2019 年 4 月 1 日星期一晚上 9:17 Oskar Karlsson通知@ github.com
写道:

@vytautas-pranskunas- https://github.com/vytautas-pranskunas- ,我会
明天发布一些其他较小的修复。


你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/tjoskar/ng-lazyload-image/issues/370#issuecomment-478709421
或静音线程
https://github.com/notifications/unsubscribe-auth/ADvMl18aKahOsS6vr4C4h4Tagwy2p4TNks5vclsrgaJpZM4Z0lGg
.

[email protected]现已出局。 让我知道错误仍然发生。

@tjoskar我一直在使用6.0.0并且问题在这里仍然存在。

// app.module.ts

LazyLoadImageModule.forRoot({
  preset: intersectionObserverPreset
}),

当我启动 SSR 服务器时,我得到:

ReferenceError: IntersectionObserver is not defined

参考 #396

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

rimlin picture rimlin  ·  5评论

kodeine picture kodeine  ·  7评论

tjoskar picture tjoskar  ·  4评论

vincent-cm picture vincent-cm  ·  10评论

sandeepdussa picture sandeepdussa  ·  9评论