Ng-lazyload-image: AngularUniversalビルドの事前レンダリングエラー

作成日 2019年01月08日  ·  23コメント  ·  ソース: tjoskar/ng-lazyload-image

  • 私は提出しています...

    • [x]バグレポート
    • []機能リクエスト
    • []サポートリクエスト
  • 機能をリクエストしバグを報告しますか?
    ライブラリとAngularUniversalビルドプリレンダー機能のバグ

  • 現在の動作は何ですか?
    コマンドを実行すると、次のようになります。
    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';
^^^^^^

SyntaxError:予期しないトークンのインポート
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)で
必要に応じて(internal / 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",

アプローチ1
プラグインルートにパッチを適用します。
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/*"] },
}

しかし、AngularUniversalでも同じエラーが発生します:(

アプローチ2
次の場所にあるサンプルプロジェクトのTypescriptビルドオプションを使用します。
https://github.com/filipesilva/angular-quickstart-lib

bug

最も参考になるコメント

Angular Universalでビルドしようとすると、同じ問題が発生します。 @tjoskar ng-packagrを使用してライブラリを構築することを考えましたか? ライブラリをFESM2015、FESM5、およびUMD形式でビルドおよびバンドルできます。
https://github.com/ng-packagr/ng-packaged/blob/master/package.json#L11(ng-packagrを使用したプロジェクトの例)を

全てのコメント23件

私も同じエラーが発生しました、AngularUniversalをインストールしています

`` `node_modules \ ng-lazyload-image \ index.js:1
(function(exports、require、module、__ filename、__ dirname){import {LazyLoadImageDirective} from './ src / lazyload-image.directive';
^^^^^^

SyntaxError:予期しないトークンのインポート
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)で
必要に応じて(internal / module.js:11:18)
評価時(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 />

私も同じエラーが発生しました、AngularUniversalをインストールしています

(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はターゲットangular universalとしてESモジュールしか持っていないため失敗すると思います。

@kmturleyが説明しているように、 ng-lazyload-imageに対して複数のターゲットを設定する必要があると思います。 しかし、それはまた、木の揺れが機能しないことを意味します。

@ xmasuku 、webpack設定の詳細な例を教えてください。 whitelistはどこで使用しますか?

@tjoskarカスタムWebpackビルドを使用しましたが、

CLIプロジェクトを生成しましたが、同じエラーが発生します

さて、今夜見てみます

Angular Universalでビルドしようとすると、同じ問題が発生します。 @tjoskar ng-packagrを使用してライブラリを構築することを考えましたか? ライブラリをFESM2015、FESM5、およびUMD形式でビルドおよびバンドルできます。
https://github.com/ng-packagr/ng-packaged/blob/master/package.json#L11(ng-packagrを使用したプロジェクトの例)を

//ユニバーサルの一般的な問題のように見えます。 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

`` `
import'zone.js / dist / zone-node ';
import {enableProdMode} from '@ angular / core';
// Express Engine
'@ nguniversal / express-engine'から{ngExpressEngine}をインポートします。
//遅延読み込み用にモジュールマップをインポートします
import {provideModuleMap} from '@ nguniversal / module-map-ngfactory-loader';

import * as express from'express ';
'path'から{join}をインポートします;

// Prodモードでのサーバーレンダリングの高速化(devモードは不要)
enableProdMode();

// Expressサーバー
const app = express();

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

// *注::このファイルはwebpackから動的にビルドされるため、require()のままにしておきます
const {AppServerModuleNgFactory、LAZY_MODULE_MAP} = require( './ dist / server / main');

//ユニバーサルエクスプレスエンジン(@ https://github.com/angular/universal/tree/master/modules/express-engineにあります)
app.engine( 'html'、ngExpressEngine({
ブートストラップ:AppServerModuleNgFactory、
プロバイダー:[
ProvideModuleMap(LAZY_MODULE_MAP)
]
}));

app.set( 'ビューエンジン'、 'html');
app.set( 'views'、DIST_FOLDER);

// Express RestAPIエンドポイントの例
// app.get( '/ api / *'、(req、res)=> {});// / browserから静的ファイルを提供しますapp.get( ' 。*'、express.static(DIST_FOLDER、{
maxAge: '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 AngularUniversalはもう壊れません:P

@Loutrinos

5.1.0リリースでは、構造が異なることがわかります

申し訳ありませんが、以前と同じ構造の新しいリリース([email protected])を作成しました。 以前の数週間はかなり忙しかったですが、今は仕事に戻っているので、それがどのように機能するかを教えてください。

5.1.1バージョンをインストールした後、次のエラーが発生します。
ReferenceError: IntersectionObserver is not defined

@agustintarifa tsconfig.jsonファイルはどのように見えますか?

https://github.com/tjoskar/ng-lazyload-image-bugs/tree/master/370-universal-starter-compileでこのリポジトリを作成しましたが、正常に動作するようになっています。 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, }),

唯一の問題は、最初の画像を表示するためにオフセットが上部で機能していないことです。少なくとも1ピクセルスクロールする必要があり、表示されているときに他の画像が読み込まれます。200ピクセル前に画像を読み込みたいです。

うーん..上記の私の例でLazyLoadImageModuleapp.moduleLazyLoadImageModuleを宣言するだけで正常に動作していて、エラーを実際に再現することはできません。 誰かがエラーを再現するために小さなリポジトリを作成できる(またはステップバイステップの説明を提供できる)と非常に役立ちます。

@agustintarifa 、オフセットの問題について。 そのための新しい問題を作成できますか?

こんにちは、v5.1.1をベータ版ではなく安定版としていつ期待できますか? 私もSSRでこの問題を抱えているからです。

@ vytautas-pranskunas-、他の小さな修正を加えて明日リリースします。

Siundsgreat👍

月、2019年4月1日には、午前9時17分PMオスカー・カールソン[email protected]
書きました:

@ 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

ref#396

このページは役に立ちましたか?
0 / 5 - 0 評価