
エントリー
シングルページアプリケーションを作成する場合、ほとんどの場合、開発者は1つの非常に一般的な問題、つまりlazyLoadモジュールの作成と、その後のクライアント側でのロードに遭遇します。 すなわち 何らかのアクションによって、または(ほとんどの場合)URLをクリックして、特定の依存関係セット(JavaScript、CSS、HTMLなど)を読み込む必要があります。 最新のフロントエンド開発の現実では、これは途方もないJavaScriptファイルになります。 この記事では、私の経験を共有し、AngularJSにlazyLoadモジュールを実装する方法を示し、それによってアプリケーションを最初にロードするときにコードの総量を削減したいと思います。
なぜAngularJS 1.x
おそらく、読者の皆さんには、「やめなさい、AngularJS 1.xとは何
ですか 。ごく最近
Angular v5.2がリリースされたからです 。」 質問は適切です。 それはシンプルで、AngularJS 1.xを使用すると同時に気分が良いプロジェクトがかなりあります。 新しいバージョンへの移行は、工数と現金の両方で非常に費用がかかる業界がいくつかあります。 AngularJS 1.xは依然として市場で非常に需要があります。
すでにある自転車
自転車ツールのフロントエンド開発の世界では、同じ問題を解決するためのアプローチが行われました-ワゴンと小さなトロリー。 誰もが自分のニーズ、スキル、知識に従って選択します。 そして、99.99%のケースに適した検証済みのソリューションはありません。 これは良くも悪くもない。 あなたはそれを受け入れて
生きる必要があります。 誰かが
RequireJS 、誰か
curl.js 、誰か
Browserify 、誰か<insert yours>を選択します。
Webpack 、
UI-Router 、および
ocLazyLoadを使用して
lazyLoadモジュールの読み込みを実装する方法を見ていきます。 すべての舞台裏の魔法は
ocLazyLoadによって行われ
ます 。 同じ
require.ensure
を使用してocLazyLoadを使用せずにlazyLoadモジュールを作成しようとすると、次のようなエラーが発生します。

プロジェクト構造
それでは始めましょう。 lazyLoadモジュールを実装する必要がある元のプロジェクトコードは共有できません。 そこで、小さなアプリケーションを作成しました。 私は、アプリケーションがどこから来てどのように機能するかが明確ではない宇宙船のように見えないようにしようとしました。 主な目的は、作業用のプロトタイプを作成すること
です。これは、
ソースコードだけでなく、 オンラインで
入手できます 。 以下に、
require-ensure
および
system-import
ブランチのプロジェクト構造を示し
require-ensure
。
import-es6
、少し追加します。
project-root ├── src │ ├── core │ │ ├── bootstrap.js │ ├── pages │ │ ├── home │ │ │ ├── about │ │ │ │ ├── about.module.js │ │ │ │ ├── about.view.html │ │ │ ├── index │ │ │ │ ├── index.module.js │ │ │ │ ├── index.view.html │ │ │ ├── home.module.js │ │ │ ├── home.module.routing.js │ │ │ ├── home.module.states.js ├── app.js ├── index.html
コードを使い始める前に、モジュールがlazyLoadであるかどうかに影響する
2つの重要なポイントについて説明しましょう。
- モジュールがlazyLoadになるために、他のモジュールの依存関係として指定する必要はありません。
- このlazyLoadモジュールを作成するルートを除き、モジュールはどこにもインポートしないでください。
あまり明確ではない場合、心配しないでください-実際には、何がすぐに明らかになります。
require.ensure()+ $ ocLazyLoad
require.ensure
は、初期バージョンでwebpackチームによって提案されました。 この方法を使用すると、開発者はコードの一部を使用して動的に個別のファイル(webpackの用語ではチャンク)を作成し、クライアント側で必要に応じてダウンロードできます。 このアプローチは、動的にロードされるモジュールの作成にはあまり好ましくありませんが、本当にしたいのであれば、それは何も悪いことではありません。 このメソッドは、高コストのリファクタリングなしでlazyLoadモジュールを作成したい人に最適です。 以下に、
require.ensure
を使用して
require.ensure
をロードする例を
require.ensure
ます。
| const homeIndex = { |
| name: "home", |
| url: "/home", |
| component: "homeComponent", |
| lazyLoad: ($transition$) => { |
| const $ocLazyLoad = $transition$.injector().get("$ocLazyLoad"); |
| |
| return require.ensure([], () => { |
| // load whole module |
| const module = require("./index/index.module"); |
| |
| $ocLazyLoad.load(module.default); |
| }, "index.module"); |
| } |
| }; |
about.module.js
モジュールパスとその他のパラメーターを除き
about.module.js
コードは同じです。 以下に、
require.ensure
を使用して
require.ensure
をロードする例を
require.ensure
ます。
| const homeAbout = { |
| name: "home.about", |
| url: "/about", |
| component: "homeAboutComponent", |
| lazyLoad: ($transition$) => { |
| const $ocLazyLoad = $transition$.injector().get("$ocLazyLoad"); |
| |
| return require.ensure([], () => { |
| // load whole module |
| let module = require("./about/about.module"); |
| |
| $ocLazyLoad.load(module.HOME_ABOUT_MODULE); |
| }, "about.module"); |
| } |
| }; |
コードからわかるように、すべての魔法はこの期間に発生します。
$ocLazyLoad.load(module.HOME_ABOUT_MODULE);
モジュールを指定する別のオプションがあります-オブジェクトを通して:
$ocLazyLoad.load({ name: "home.module" });
しかし、この場合、行動の自由に限定されます。 モジュールの名前を変更する場合は、いくつかの場所でコードを変更する必要があります。 また、モジュール名を書くときに間違いを犯す可能性が高くなります。
このアプローチを使用しないことを強くお勧めします。about.module.js
とそれに続くクライアント側へのダウンロードに関する1つの重要なニュアンスに注意を喚起したいと思います。 以下の画面を見てください:
Home/About
リンクをクリックすると、
index.module.chunk.js
と
about.module.chunk.js
2つのファイルが一度にロードされます。 これは、
home.about
URLが
home
URLの子であるためです。 これは覚えておく価値があります。 少し先に進んで、最後のセクションでは、新しいURLで別のモジュールを追加し、1つのファイルだけがロードされ、それ以外は何も読み込まれないことを確認します。
System.import + $ ocLazyLoad
私は長い間、このアプローチについて書くかどうかを考えました。 彼について話す必要があると思います。
System.importは、
その後禁止されたwebpackチームとは異なる構成ですが、このアプローチは実装オプションとして引き続き提供されます。 さらに、この設計は、新しいバージョンのwebpackでも引き続き機能します。 これは互換性の理由で行われたと思われます。 プロジェクトでこの構成を使用する場合、悪いニュースがあります-
廃止された状態です。 このセクションにはコードはありません。 どうぞ
動的インポート+ $ ocLazyLoad
Chrome 63とSafari Technology Preview 24がロールアウトされたアップデートと動的インポートが開発者に利用可能になったことを既に聞いたことがあるかもしれません。 はい、はい、
仕様で提案された非常に動的なインポート。
2016年に、webpackチームは動的インポートのサポートを導入しました。
このセクションでは、
pages
ディレクトリのルートに別のモジュールを追加して、lazyLoadが適切に機能することを確認します。
import-es6
の構造は次のとおりです。
project-root ├── src │ ├── core │ │ ├── bootstrap.js │ ├── pages │ │ ├── blog │ │ │ ├── blog.module.js │ │ │ ├── blog.service.js │ │ │ ├── blog.view.html │ │ ├── home │ │ │ ├── about │ │ │ │ ├── about.module.js │ │ │ │ ├── about.view.html │ │ │ ├── index │ │ │ │ ├── index.module.js │ │ │ │ ├── index.view.html │ │ │ ├── home.module.js │ │ │ ├── home.module.routing.js │ │ │ ├── home.module.states.js ├── app.js ├── app.routing ├── app.states.js ├── index.html
プロジェクトで
Babelまたは
TypeScriptを使用しない場合、タンバリンを使用した不要なダンスなしですべてがボックスから開始されます。 しかし、あなたと私は、現代のフロントエンドの現実では、BabelやTypeScriptなしでコードを書くことは非常に難しいことを知っています。 バベルについて話しましょう。 まず、ダイナミックインポートの構文を理解するBabel用の追加プラグインをインストールする必要があります:
syntax-dynamic-import 。 そうでない場合、エラーが発生します。

次に、設定で
.babelrc
を追加する必要があります。
| { |
| "presets": [ |
| [ |
| "env", |
| { |
| "targets": { |
| "browsers": [ |
| "last 2 versions", |
| "safari 7" |
| ] |
| } |
| } |
| ] |
| ], |
| "plugins": [ |
| "syntax-dynamic-import" |
| ] |
| } |
次に、以下に示す2番目の厄介な間違いを示します。

はい、あなたは間違って
いませんでした 、
ESLintは動的インポートも理解していません 。 これを修正するには、ESLint
babel-eslint用の特別なパーサーをインストールする必要があります。そうすると、すべてが時計仕掛けのように機能します。 設定で
.eslintrc
を追加します。
| { |
| "extends": "eslint:recommended", |
| "parser": "babel-eslint", |
| "parserOptions": { |
| "ecmaVersion": 6, |
| "sourceType": "module", |
| "ecmaFeatures": { |
| "impliedStrict": false |
| } |
| }, |
| "env": { |
| "browser": true, |
| "node": true, |
| "es6": true |
| } |
| } |
それでは、動的インポートを実際に試してみましょう。 新しいモジュールでテストします。
| const appBlog = { |
| name: "blog", |
| url: "/blog", |
| component: "blogComponent", |
| lazyLoad: ($transition$) => { |
| const $ocLazyLoad = $transition$.injector().get("$ocLazyLoad"); |
| |
| // !!! Dynamic import !!! |
| return import(/* webpackChunkName: "blog.module" */ "./pages/blog/blog.module") |
| .then(mod => $ocLazyLoad.load(mod.BLOG_MODULE)) |
| .catch(err => { |
| throw new Error("Ooops, something went wrong, " + err); |
| }); |
| } |
| }; |
コードからわかるように、webpackチームは動的インポートにいくつかの素晴らしい機能を追加しました。 webpackが作成する最終チャンクの名前を指定することは可能で、ロード方法も指定できます。 詳細は
こちらをご覧ください 。 以下のビデオでは、動的インポートの動作を確認できます。
コンポーネントと テンプレート
モジュールをロードするために、
component
プロパティが使用されました。
component
プロパティの代わりに
template
と呼ばれるプロパティを使用できます。 動作はほとんど同じで、ニュアンスは1つだけです。 コンポーネントの名前のスペルを間違えた場合、または他の何らかの理由でコンポーネントが使用できない場合、コンソールにエラーが表示されます。
template
すると、このようなエラーは発生しません。 そして、あなたは問題が何であるかを非常に長い間探すことができる。
便利なリンク
- AngularJS 1.5コンポーネントにルーティングする方法
- UI-Routerの遅延読み込み
- GitHubソースコード
- Herokuのプロジェクト
結論の代わりに
AngularJSアプリケーションのコンテキストでのlazyLoadモジュールは、アプリケーションの軽量化、応答性の向上、分散化を実現する絶好の機会です。 時代は変化し、アプリケーションの要件は増大し、それに伴い、クライアントに提供するコードの量も増大しています。 以前にすべてのコードを1つのファイルに集めて、それをエンドユーザーに渡せば十分で、すべてがクールだった場合、これは容認できない贅沢です。 共通コードの割り当てにより、URLに応じてアプリケーションを分割する傾向があります。
以上です。 ご清聴ありがとうございました。 最後まで読んでくれた人、ありがとう。
PS AngularJSアプリケーション用のlazyLoadモジュールの実装で同様の経験がある場合は、コメントで共有してください。