Визначте глобальну змінну за допомогою webpack


138

Чи можна визначити глобальну змінну за допомогою webpack, щоб отримати щось подібне:

var myvar = {};

Усі приклади, які я бачив, використовували зовнішній файл require("imports?$=jquery!./file.js")

Відповіді:


272

Є кілька способів наблизитись до глобальних:

1) Помістіть свої змінні в модуль.

Webpack оцінює модулі лише один раз, тому ваш примірник залишається глобальним і здійснює зміни від модуля до модуля. Отже, якщо ви створюєте щось на кшталт a globals.jsі експортуєте об'єкт усіх своїх глобальних тонів, ви можете import './globals'і читати / писати в ці глобалі. Ви можете імпортувати в один модуль, вносити зміни до об'єкта з функції та імпортувати в інший модуль і читати ці зміни у функції. Також пам’ятайте про порядок того, що відбувається. Вебпакет спочатку візьме весь імпорт і завантажить їх, щоб розпочати з вашого entry.js. Тоді воно виконає entry.js. Тож там, де ви читаєте / пишете в глобальних мережах, важливо. Це з кореневої області модуля або у функції, названій пізніше?

Примітка . Якщо ви хочете, щоб екземпляр був newкожен раз, тоді використовуйте клас ES6 . Традиційно в JS ви використовуєте великі регістри класів (на відміну від малих літер для об'єктів)
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()

2) Провідний модуль Webpack

Ось як це можна зробити за допомогою ProvidePlugin Webpack (який робить модуль доступним як змінну у кожному модулі та лише ті модулі, де ви його фактично використовуєте). Це корисно, коли ви не хочете продовжувати друкувати import Bar from 'foo'знову і знову. Або ви можете принести сюди такий пакет, як jQuery, або lodash як глобальний (хоча ви можете поглянути на зовнішні програми Webpack ).

Крок 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.

Примітка. Не забудьте розповісти вашому літеру про глобальний, щоб він не скаржився. Наприклад, дивіться мою відповідь на ESLint тут .

3) Використовуйте DefinePlugin Webpack

Якщо ви просто хочете використовувати 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, якщо є якісь ключі / облікові дані) та додасть ваші змінні конфігурації до об'єкта Node.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 , використовуйте її, якщо ви хочете виключити включення деяких модулів до складу вбудованого пакета. Webpack зробить модуль глобально доступним, але не поставить його у свій пакет. Це зручно для великих бібліотек, таких як jQuery (оскільки струшування дерев зовнішніми пакетами не працює в Webpack ), де вони завантажені на вашу сторінку вже в окремих тегах сценарію (можливо, з CDN).


3
+1. Я реструктуризую додаток, щоб використовувати веб-пакет як інструмент збирання, і це спочатку не працювало для мене, тому що я не включив посилання на власний utilsпростір імен у цільовий файл - спочатку я просто поставив точку перелому в браузері вікно джерела, і я не спалахнув, чому utilsне було визначено. Нарешті я виявив, що webpack (досить розумно) включає модуль лише у тому випадку, якщо його простір імен посилається хоча б один раз. Тому, коли я зробив передмову з однією з функцій утиліти цільового файлу utils, модуль був включений.
nb1987

Так, це робить його доступним лише тоді, коли ви його використовуєте. Я поставив це в першому рядку відповіді, але я вніс невелику корекцію, тож, можливо, він читається краще. Дякуємо за +1!
програмамер

1
Зауважте, що ProvidePlugin насправді завантажує модулі, і якщо вам просто потрібна змінна, вона не працює таким чином. Просто використовуйте externalsзамість цього, якщо вам потрібно створити глобальну змінну. Приклад: externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, }, Потім використовуйте його якconst webpackVariables = require('webpackVariables');
Брайан Хаак,

1
А чи знаєте ви, як я можу використовувати цей підхід із TypeScript? Там, якщо ви використовуєте незадекларовану змінну, вона видає помилку ...
knaos

2
@prograhammer Насправді я вже знайшов рішення. У корені програми, зазвичай там, де знаходиться ваш tsconfig.json , вам потрібно додати файл визначення з назвою global.d.ts . У ньому ви можете оголосити глобальні змінні, як це: declare const isProduction: bool;Для довідки, перевірити це typescriptlang.org/docs/handbook/declaration-files/templates / ...
knaos

45

Я збирався задати саме таке питання. Провівши трохи далі та переглянувши частину документації веб-пакету, я думаю, що ви хочете, це output.libraryі output.libraryTargetу webpack.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

myLibrary дає невизначений в іншому файлі в моєму випадку. Чи можете ви мені допомогти
RVCoder

17

Використовуйте DefinePlugin .

DefinePlugin дозволяє створювати глобальні константи, які можна налаштувати під час компіляції.

new webpack.DefinePlugin(definitions)

Приклад:

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

Використання:

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

14

Ви можете використовувати визначити window.myvar = {}. Коли ви хочете використовувати його, ви можете використовувати якwindow.myvar = 1


Це не працює з EMCAScript 6. Створює помилку з var window.CKEDITOR_BASEPATH = {};помилкою "Несподіваний жетон" післяwindow.
Routhinator

1
Вибачте. Я щойно оновив свою відповідь. Вам слід varнадати ключове слово. window.CKEDITOR_BASEPATH = {};
Anh Nguyen

Це працює, на жаль, проблема, яка у мене виникає, полягає в тому, що мені потрібно завантажити його в пакет перед CKEditor, проте Webpack наполягає на тому, щоб розмістити його після того, куди я розміщую його в моєму імпорті / js. : /
Ротатор

2

Я вирішив це питання, встановивши глобальні змінні як статичні властивості для класів, до яких вони найбільш актуальні. У ES5 це виглядає приблизно так:

var Foo = function(){...};
Foo.globalVar = {};
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.