簡體   English   中英

使用 webpack 定義全局變量

[英]Define global variable with webpack

是否可以用 webpack 定義一個全局變量來產生這樣的結果:

var myvar = {};

我看到的所有示例都使用外部文件require("imports?$=jquery!./file.js")

有幾種方法可以處理全局變量:

  1. 把你的變量放在一個模塊中。

Webpack 只對模塊進行一次評估,因此您的實例保持全局並在模塊之間進行更改。 因此,如果您創建類似globals.js並導出所有全局變量的對象,那么您可以import './globals'並讀取/寫入這些全局變量。 您可以導入一個模塊,從一個函數更改對象,然后導入另一個模塊並讀取函數中的這些更改。 還要記住事情發生的順序。 Webpack 將首先獲取所有導入並從entry.js開始按順序加載它們。 然后它將執行entry.js 所以你在哪里讀/寫全局變量很重要。 它是來自模塊的根范圍還是在稍后調用的函數中?

配置文件

export default {
    FOO: 'bar'
}

一些文件.js

import CONFIG from './config.js'
console.log(`FOO: ${CONFIG.FOO}`)

注意:如果您希望實例每次都是new ,請使用ES6 類 傳統上,在 JS 中,您會大寫類(而不是小寫的對象),例如
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()

  1. 的WebPack的ProvidePlugin

以下是如何使用 Webpack 的 ProvidePlugin(它使模塊可用作每個模塊中的變量,並且僅在您實際使用它的那些模塊中可用)。 當您不想一次又一次地輸入import Bar from 'foo'時,這很有用。 或者,您可以在此處引入像 jQuery 或 lodash 這樣的全局包(盡管您可能會查看 Webpack 的Externals )。

步驟 1) 創建任何模塊。 例如,一組全局實用程序會很方便:

實用程序.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'
    })
  ]  

}

現在只需在任何 js 文件中調用utils.sayHello()就可以了。 如果您在 Webpack 中使用它,請確保重新啟動您的開發服務器。

注意:不要忘記告訴你的 linter 關於全局,這樣它就不會抱怨。 例如,請在此處查看我對 ESLint 的回答

  1. 使用 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");
  1. 使用全局窗口對象(或 Node 的全局)

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/

你會看到這通常用於 polyfills,例如: window.Promise = Bluebird

  1. 使用像dotenv這樣的包

(對於服務器端項目) dotenv 包將采用本地配置文件(如果有任何密鑰/憑據,您可以將其添加到 .gitignore 中)並將您的配置變量添加到 Node 的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)中將這些加載到頁面上。

我正要問同樣的問題。 在進一步搜索並解密 webpack 文檔的一部分后,我認為您想要的是webpack.config.js文件output.libraryTargetoutput.libraryoutput.libraryTarget

例如:

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

使用定義插件

DefinePlugin 允許您創建可以在編譯時配置的全局常量。

new webpack.DefinePlugin(definitions)

例子:

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

用法:

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

您可以使用定義window.myvar = {} 當你想使用它時,你可以使用 like window.myvar = 1

我通過將全局變量設置為與它們最相關的類的靜態屬性來解決這個問題。 在 ES5 中,它看起來像這樣:

var Foo = function(){...};
Foo.globalVar = {};

DefinePlugin 實際上並沒有定義任何東西。 它所做的是替換包代碼中存在的變量。 如果您的代碼中不存在該變量,則它什么也不做。 所以它不會創建全局變量。

為了創建一個全局變量,將它寫在你的代碼中:

window.MyGlobal = MY_GLOBAL; 

並使用 DefinePlugin 用一些代碼替換MY_GLOBAL

new webpack.DefinePlugin({
    'MY_GLOBAL': `'foo'`,
    // or
    'MY_GLOBAL': `Math.random()`,
}),

那么你的輸出 JS 將是這樣的:

window.MyGlobal = 'foo';
// or
window.MyGlobal = Math.random(); 

但是MY_GLOBAL永遠不會在運行時實際存在,因為它永遠不會被定義。 所以這就是 DefinePlugin 有一個誤導性名稱的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM