AngularJS + Webpack = lazyLoad

AngularJS + Webpack = lazyLoad

エントリー


シングルページアプリケーションを作成する場合、ほとんどの場合、開発者は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>を選択します。 WebpackUI-Router 、およびocLazyLoadを使用してlazyLoadモジュールの読み込みを実装する方法を見ていきます。 すべての舞台裏の魔法はocLazyLoadによって行われます 。 同じrequire.ensureを使用してocLazyLoadを使用せずにlazyLoadモジュールを作成しようとすると、次のようなエラーが発生します。

require.ensureエラー

プロジェクト構造


それでは始めましょう。 lazyLoadモジュールを実装する必要がある元のプロジェクトコードは共有できません。 そこで、小さなアプリケーションを作成しました。 私は、アプリケーションがどこから来てどのように機能するかが明確ではない宇宙船のように見えないようにしようとしました。 主な目的は、作業用のプロトタイプを作成することです。これは、 ソースコードだけでなく、 オンライン入手できます 。 以下に、 require-ensureおよびsystem-importブランチのプロジェクト構造を示しrequire-ensureimport-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つの重要なポイントについて説明しましょう。

  1. モジュールがlazyLoadになるために、他のモジュールの依存関係として指定する必要はありません。
  2. この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");
}
};
view raw homeIndex.js hosted with ❤ by GitHub
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");
}
};
view raw homeAbout.js hosted with ❤ by GitHub
コードからわかるように、すべての魔法はこの期間に発生します。

 $ocLazyLoad.load(module.HOME_ABOUT_MODULE); 

モジュールを指定する別のオプションがあります-オブジェクトを通して:

 $ocLazyLoad.load({ name: "home.module" }); 

しかし、この場合、行動の自由に限定されます。 モジュールの名前を変更する場合は、いくつかの場所でコードを変更する必要があります。 また、モジュール名を書くときに間違いを犯す可能性が高くなります。 このアプローチを使用しないことを強くお勧めします。

about.module.jsとそれに続くクライアント側へのダウンロードに関する1つの重要なニュアンスに注意を喚起したいと思います。 以下の画面を見てください:


Home/Aboutリンクをクリックすると、 index.module.chunk.jsabout.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 。 そうでない場合、エラーが発生します。

Babel構文エラー

次に、設定で.babelrcを追加する必要があります。

{
"presets": [
[
"env",
{
"targets": {
"browsers": [
"last 2 versions",
"safari 7"
]
}
}
]
],
"plugins": [
"syntax-dynamic-import"
]
}
view raw .babelrc hosted with ❤ by GitHub
次に、以下に示す2番目の厄介な間違いを示します。

ESLint構文エラー

はい、あなたは間違っていませんでした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
}
}
view raw .eslintrc hosted with ❤ by GitHub
それでは、動的インポートを実際に試してみましょう。 新しいモジュールでテストします。

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);
});
}
};
view raw appBlog.js hosted with ❤ by GitHub
コードからわかるように、webpackチームは動的インポートにいくつかの素晴らしい機能を追加しました。 webpackが作成する最終チャンクの名前を指定することは可能で、ロード方法も指定できます。 詳細はこちらをご覧ください 。 以下のビデオでは、動的インポートの動作を確認できます。


コンポーネントと テンプレート


モジュールをロードするために、 componentプロパティが使用されました。 componentプロパティの代わりにtemplateと呼ばれるプロパティを使用できます。 動作はほとんど同じで、ニュアンスは1つだけです。 コンポーネントの名前のスペルを間違えた場合、または他の何らかの理由でコンポーネントが使用できない場合、コンソールにエラーが表示されます。 templateすると、このようなエラーは発生しません。 そして、あなたは問題が何であるかを非常に長い間探すことができる。

便利なリンク


  1. AngularJS 1.5コンポーネントにルーティングする方法
  2. UI-Routerの遅延読み込み
  3. GitHubソースコード
  4. Herokuのプロジェクト

結論の代わりに


AngularJSアプリケーションのコンテキストでのlazyLoadモジュールは、アプリケーションの軽量化、応答性の向上、分散化を実現する絶好の機会です。 時代は変化し、アプリケーションの要件は増大し、それに伴い、クライアントに提供するコードの量も増大しています。 以前にすべてのコードを1つのファイルに集めて、それをエンドユーザーに渡せば十分で、すべてがクールだった場合、これは容認できない贅沢です。 共通コードの割り当てにより、URLに応じてアプリケーションを分割する傾向があります。

以上です。 ご清聴ありがとうございました。 最後まで読んでくれた人、ありがとう。

PS AngularJSアプリケーション用のlazyLoadモジュールの実装で同様の経験がある場合は、コメントで共有してください。

Source: https://habr.com/ru/post/J346406/


All Articles