ホームページ  >  記事  >  ウェブフロントエンド  >  Webpack モジュールを使用してライブラリをパッケージ化する原理と実装

Webpack モジュールを使用してライブラリをパッケージ化する原理と実装

亚连
亚连オリジナル
2018-05-31 13:53:281910ブラウズ

この記事では主に webpack 組織モジュールのパッケージ化ライブラリの原理と実装について紹介し、参考にさせていただきます。

前回の記事では、JS モジュールをパッケージ化する Webpack の基本原理を分析しました。紹介されたケースは最も一般的な状況です。つまり、複数の JS モジュールとエントリー モジュールが 1 つのバンドル ファイルにパッケージ化されており、ブラウザーやブラウザーで直接使用できます。他の JavaScript エンジンによる実行は、完全な実行可能ファイルを生成する直接コンパイルと同等です。ただし、別の非常に一般的な状況があります。つまり、JavaScript ライブラリを構築して公開したい場合です。たとえば、npm コミュニティで独自のライブラリを公開する場合、Webpack には対応する構成が必要となり、コンパイルされたコードは若干異なります。 。

前の記事と同様に、この記事では主に Webpack の生成されたコードを分析し、それを組み合わせて、ライブラリをコンパイルする際の Webpack のライブラリ設定オプションの特定の役割を説明します。対応する公式ドキュメントはここにあります。

JS を作成するためのライブラリ

簡単なケースから始めましょう。単純なライブラリ util.js を作成します。実際には役に立たず、純粋に教育の参考のみを目的としています。 。 。

次に、Webpack の設定を書きます:

import $ from 'jquery'

function sayHello() {
 console.log("Hello");
}

function hideImages() {
 $('img').hide();
}

export default {
 sayHello: sayHello,
 hideImages: hideImages
}

ただし、これだけでは不十分です。出力ファイルはすぐに実行される関数であり、最後に util.js のエクスポートが返されます。前回の記事で分析した結果、最終的に生成されたバンドルのコード構造はおおよそ次のようになります:

// 入口文件
entry: {
 util: './util.js',
}

// 输出文件
output: {
 path: './dist',
 filename: '[name].dist.js'
}

実行されれば終了です。util.js のエクスポート部分を返すだけです。必要なのは以下のことです。この戻り値をコンパイル済みファイルの module.export に渡すと、コンパイル済みファイルは他の人がインポートできるライブラリになります。したがって、取得したいコンパイル済みファイルは次のようになります:

(function(modules) {
 var installedModules = {};
 
 function webpack_require(moduleId) {
   // ...
 }

 return webpack_require('./util.js');
}) ({
 './util.js': generated_util,
 '/path/to/jquery.js': generated_jquery
});

このような結果を得るには、Webpack 設定の出力部分にライブラリ情報を追加する必要があります:

module.exports = (function(modules) {
 var installedModules = {};
 function webpack_require(moduleId) {
   // ...
 }
 return webpack_require('./util.js');
}) ({
 './util.js': generated_util,
 '/path/to/jquery.js': generated_jquery
});

ここで最も重要なことは libraryTarget です。現在 commonjs2 形式を使用すると、上記のコンパイル結果が得られます。これは、Webpack ライブラリが最終出力を CommonJS 形式でエクスポートすることを意味し、これによりライブラリのリリースが実現します。

その他の公開形式

commonjs2 に加えて、libraryTarget には他のオプションもあります:

// 入口文件
output: {
 path: './dist',
 filename: '[name].dist.js',

 library: 'util',
 libraryTarget: commonjs2
}

さまざまなオプションを使用すると、コンパイルされたファイルをさまざまな JavaScript 実行環境で使用できます。ここでは、Tiger Balm umd 形式の出力がどのようになるかを直接確認します。

var (默认值,发布为全局变量)
commonjs
commonjs2
amd
umd

は、さまざまな異なるケースを処理する必要があるため、前の commonjs2 の状況よりもはるかに複雑ですが、実際には次の部分も同様です。最も重要なのは最初の数行で、これは umd モジュールを記述する標準的な方法です。渡されたファクトリ関数 (実際にはモジュールをロードする関数) を実行し、返された結果をさまざまな動作環境に応じて対応するオブジェクトに渡します。たとえば、var は結果をグローバル変数として設定します。これは、ブラウザが 3f1c4e4b6b16bbbd69b2ee476dc4f83a タグを通じて JS ファイルを直接インポートするために使用します。 AMD 環境の場合、標準 AMD 書き込みも使用されます。このようにして、公開された JS ライブラリは、他の人がどの環境でも使用できます。

targetExport は出力コンテンツを制御します

umd 形式を使用してパッケージ化する場合、例の util のようにライブラリのソース コードが ES6 形式のエクスポート デフォルトを使用して出力される場合、注意が必要な落とし穴がある可能性があります。 .js を直接配置すると、コンパイルされた JS ライブラリ ファイルをブラウザで使用できます。これは、<script> または RequireJS である可能性があります。必要な結果が得られない場合があります。これは、JS ファイルが、期待したものではなく、次のようなオブジェクトを返しているためです: </script>

(function webpackUniversalModuleDefinition(root, factory) {
 if(typeof exports === &#39;object&#39; && typeof module === &#39;object&#39;) // commonjs2
  module.exports = factory();
 else if(typeof define === &#39;function&#39; && define.amd)
  define("util", [], factory); // amd
 else if(typeof exports === &#39;object&#39;)
  exports["util"] = factory(); // commonjs
 else
  root["util"] = factory(); // var
}) (window, function() {
 return (function(modules) {
  var installedModules = {};
  function webpack_require(moduleId) {
    // ...
  }
  return webpack_require(&#39;./util.js&#39;);
 }) ({
  &#39;./util.js&#39;: generated_util,
  &#39;/path/to/jquery.js&#39;: generated_jquery
 });
}

ブラウザだけでなく、ES6 をサポートしていないモジュール システムでもこの問題は発生します。これもデフォルトを知らないために発生します。したがって、コンパイルされた JS ファイルは実際にはデフォルトのみを出力する必要があり、これは Webpack 設定の targetExport によって制御する必要があります:

library: 'util',

libraryTarget: umd,

targetExport: 'default'

このようにFactory は戻り値の後に ['default'] を追加し、エクスポートのデフォルト部分のみが返されるようにします。

この落とし穴は、umd 形式では非常に簡単に発生します。たとえば、Vue コンポーネントを公開する場合、通常、.vue ファイル内の JavaScript 部分は、次のようなエクスポートのデフォルト形式で Component オブジェクトをエクスポートします。

{
 &#39;default&#39;: {
  sayHello: sayHello,
  hideImages: hideImages
 }
}

コンパイルされた JS ファイルをブラウザで直接実行し、CDN を使用して 3f1c4e4b6b16bbbd69b2ee476dc4f83a を通じて Vue をロードすると、取得するオブジェクトが多すぎるため、Vue がこのコンポーネントを認識できないことがわかります。デフォルトの不要なレイヤーが追加されます。

出力コンテンツをデフォルトに変更すると、ES6 環境でのこのモジュールの使用に影響しますか?一般的に言って、いいえ。前の記事で述べたように、Webpack の生成されたコードでモジュールが導入されると、__esModule と呼ばれる値を通じてそれが ES6 形式でのエクスポートであるかどうかが設定および決定されます。デフォルトの部分のみがエクスポートされる場合、このオブジェクトは非であるとみなされます。 ES6 には __esModule が含まれていないためです。このようにして、他のモジュールがインポートを通じてこのモジュールを導入すると、オブジェクト全体がインポートされます。これは実際には、元のモジュールのエクスポートのデフォルト部分だけを偽装してインポートするのと同じです。

もちろん、上記の議論の前提は、エクスポートする必要があるすべてのコンテンツがエクスポートのデフォルトにあるということです。デフォルトと通常の両方のエクスポートがある場合、コンパイルされたファイルでデフォルトの部分のみをエクスポートすることは明らかに不可能です。

上記は私があなたのためにまとめたものです。

関連記事:

ブロックチェーンを実装するための200行のコード ブロックチェーンのサンプルの詳細な説明

vue facebook twitterを使用してサンプルを共有

reactはcreate-react-appに基づいてプロジェクトを作成します

以上がWebpack モジュールを使用してライブラリをパッケージ化する原理と実装の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。