webpackでグローバル変数を定義する


138

次のような結果になるようにwebpackでグローバル変数を定義することは可能ですか?

var myvar = {};

私が見た例はすべて外部ファイルを使用していた require("imports?$=jquery!./file.js")

回答:


272

グローバルにアプローチする方法はいくつかあります。

1)変数をモジュールに入れます。

Webpackはモジュールを1回だけ評価するため、インスタンスはグローバルのままであり、モジュール間で変更が伝達されます。したがって、のようなものを作成しglobals.js、すべてのグローバルのオブジェクトをエクスポートするimport './globals'と、これらのグローバルに対して読み取り/書き込みを行うことができます。1つのモジュールにインポートして、関数からオブジェクトに変更を加え、別のモジュールにインポートして、それらの変更を関数で読み取ることができます。物事が起こる順序も覚えておいてください。Webpackは最初にすべてのインポートを取得し、から順にロードしますentry.js。その後、実行されentry.jsます。したがって、グローバルへの読み取り/書き込みを行う場所が重要です。それはモジュールのルートスコープからですか、それとも後で呼び出される関数内ですか?

:インスタンスをnew毎回使用する場合は、ES6クラスを使用します。伝統的にJSでは、オブジェクトの小文字ではなくクラスを大文字にします
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()

2)WebpackのProvidePlugin

ここでは、WebpackのProvidePluginを使用してそれを行う方法を示します(これにより、モジュールがすべてのモジュールで変数として使用可能になり、実際に使用するモジュールのみが使用可能になります)。これは、何度も入力し続けたくない場合に便利ですimport Bar from 'foo'。または、jQueryやlodashなどのパッケージをグローバルとしてここに取り込むこともできます(ただし、WebpackのExternalsを確認することもできます)。

手順1)モジュールを作成します。たとえば、ユーティリティのグローバルセットは便利です。

utils.js

export function sayHello () {
  console.log('hello')
}

ステップ2)モジュールにエイリアスを付けて、ProvidePluginに追加します。

webpack.config.js

var webpack = require("webpack");
var path = require("path");

// ...

module.exports = {

  // ...

  resolve: {
    extensions: ['', '.js'],
    alias: {
      'utils': path.resolve(__dirname, './utils')  // <-- When you build or restart dev-server, you'll get an error if the path to your utils.js file is incorrect.
    }
  },

  plugins: [

    // ...

    new webpack.ProvidePlugin({
      'utils': 'utils'
    })
  ]  

}

ここでutils.sayHello()、任意のjsファイルを呼び出すだけで動作します。Webpackで使用している場合は、必ずdev-serverを再起動してください。

注:リンターにグローバルについて通知することを忘れないでください。たとえば、ESLintに対する私の回答はこちらを参照してください

3)WebpackのDefinePluginを使用する

グローバルの文字列値でconstを使用したいだけの場合は、このプラグインをWebpackプラグインのリストに追加できます。

new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object")
})

次のように使用します。

console.log("Running App version " + VERSION);
if(!BROWSER_SUPPORTS_HTML5) require("html5shiv");

4)グローバルウィンドウオブジェクト(またはノードのグローバル)を使用する

window.foo = 'bar'  // For SPA's, browser environment.
global.foo = 'bar'  // Webpack will automatically convert this to window if your project is targeted for web (default), read more here: https://webpack.js.org/configuration/node/

たとえば、これはポリフィルに一般的に使用されていることがわかります。 window.Promise = Bluebird

5)dotenvのようなパッケージを使用する

(サーバー側プロジェクトの場合)dotenvパッケージはローカル構成ファイル(キー/資格情報がある場合は.gitignoreに追加できます)を取得し、構成変数をノードのprocess.envオブジェクトに追加します。

// As early as possible in your application, require and configure dotenv.    
require('dotenv').config()

.envプロジェクトのルートディレクトリにファイルを作成します。の形式で環境固有の変数を新しい行に追加しますNAME=VALUE。例えば:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

それでおしまい。

process.envこれで、.envファイルで定義したキーと値が得られました。

var db = require('db')
db.connect({
  host: process.env.DB_HOST,
  username: process.env.DB_USER,
  password: process.env.DB_PASS
})

ノート:

WebpackのExternalsについては、ビルドしたバンドルに含まれていないモジュールを除外する場合に使用します。Webpackはモジュールをグローバルに利用可能にしますが、バンドルに含めません。これは、jQueryのような大きなライブラリ(Webpackではツリーの揺れの外部パッケージが機能しないため)に便利です。これらは、(おそらくCDNから)別のスクリプトタグでページにロードされています。


3
+1。ビルドツールとしてwebpackを利用するようにアプリを再構築していutilsますが、ターゲットファイルに自分の名前空間への参照を含めていなかったため、これは最初は機能しませんでした。ソースウィンドウと私はなぜutils定義されなかったのかと戸惑い続けました。最後に、名前空間が少なくとも1回参照されている場合にのみ、webpackが(かなりスマートに)モジュールを含むことを発見しました。したがって、ターゲットファイルのユーティリティ関数の1つをで序文にするとutils、モジュール含まれていました。
nb1987

うん、あなたがそれを使用する場所でのみ、それを利用可能にします。私はそれを答えの最初の行に入れましたが、少し調整したので、多分それがよりよく読めるでしょう。+1をありがとう!
プログラハンマー2017年

1
ProvidePluginは実際にモジュールをロードすることに注意してください。変数のみが必要な場合は、そのようには機能しません。externalsグローバル変数を作成する必要がある場合は、代わりに使用してください。例:externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, }, 次に、次のように使用しますconst webpackVariables = require('webpackVariables');
Brian Haak

1
TypeScriptでこのアプローチをどのように使用できるか知っていますか?宣言されていない変数を使用すると、エラーがスローされます...
knaos

2
@prograhammer実際、私はすでに解決策を見つけました。アプリケーションのルートでは、通常、あなたのところtsconfig.jsonである、あなたは、名前の定義ファイルを追加する必要がありglobal.d.tsを。その中で、次のようにグローバル変数を宣言できますdeclare const isProduction: bool;。参考として、typescriptlang.org
docs / handbook / declaration

45

私も同じ質問をしようとしていました。webpackのドキュメントの一部をさらに検索し、解読した後、必要なのはファイル内とファイル内にあるoutput.libraryと思います。output.libraryTargetwebpack.config.js

例えば:

js / index.js:

var foo = 3;
var bar = true;

webpack.config.js

module.exports = {
   ...
   entry: './js/index.js',
   output: {
      path: './www/js/',
      filename: 'index.js',
      library: 'myLibrary',
      libraryTarget: 'var'
   ...
}

生成されたwww/js/index.jsファイルをhtmlスクリプトタグでリンクするmyLibrary.fooと、他のスクリプトのどこからでもアクセスできるようになります。


3
私はこれが欠落export { foo }していると思いますindex.jsか?
LondonAppDev 2018年

myLibraryは、私の場合、別のファイルでundefinedを提供します。私を助けてください
RVCoder

17

DefinePluginを使用します

DefinePluginを使用すると、コンパイル時に構成できるグローバル定数を作成できます。

new webpack.DefinePlugin(definitions)

例:

plugins: [
  new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true)
  })
  //...
]

使用法:

console.log(`Environment is in production: ${PRODUCTION}`);

14

defineを使用できますwindow.myvar = {}。使いたい時はwindow.myvar = 1


これはEMCAScript 6では機能しません。var window.CKEDITOR_BASEPATH = {};エラーは「Unexpected Token」の後に生成されますwindow.
Routhinator

1
ごめんなさい。回答を更新しました。varキーワードを付ける必要があります。 window.CKEDITOR_BASEPATH = {};
Anh Nguyen 2017年

これは機能しますが、残念なことに、CKEditorの前にバンドルにロードする必要があるという問題がありますが、Webpackはimports / jsのどこに配置しても問題なく配置することを求めています。:/
Routhinator 2017年

2

グローバル変数を最も関連のあるクラスの静的プロパティとして設定することで、この問題を解決しました。ES5では次のようになります。

var Foo = function(){...};
Foo.globalVar = {};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.