Условная сборка на основе среды с использованием Webpack


у меня есть некоторые вещи для разработки - например, насмешки, которые я хотел бы не раздувать мой распределенный файл сборки.

в RequireJS вы можете передать конфигурацию в файле плагина и условно требовать вещи на основе этого.

для webpack, похоже, нет способа сделать это. Во-первых, чтобы создать конфигурацию среды выполнения для среды, которую я использовал разрешить.псевдоним для перестановки требуется в зависимости от окружающей среды, например:

// All settings.
var all = {
    fish: 'salmon'
};

// `envsettings` is an alias resolved at build time.
module.exports = Object.assign(all, require('envsettings'));

затем при создании конфигурации webpack я могу динамически назначить какой файл envsettings указывает на (т. е. webpackConfig.resolve.alias.envsettings = './' + env).

Я хотел бы сделать что-то вроде:
if (settings.mock) {
    // Short-circuit ajax calls.
    // Require in all the mock modules.
}

но, очевидно, я не хочу создавать эти макетные файлы, если среда не является макетом.

Я мог бы вручную переставить все эти требования в файл заглушки с помощью resolve.снова псевдоним - но есть ли способ, который чувствует себя менее хакерским?

любые идеи как я могу это сделать? Спасибо.

7 59

7 ответов:

можно использовать определить плагин.

Я использую его, делая что-то столь же простое, как это в вашем файле сборки webpack, где env - путь к файлу, который экспортирует объект параметры:

// Webpack build config
plugins: [
    new webpack.DefinePlugin({
        ENV: require(path.join(__dirname, './path-to-env-files/', env))
    })
]

// Settings file located at `path-to-env-files/dev.js`
module.exports = { debug: true };

а потом это в вашем коде

if (ENV.debug) {
    console.log('Yo!');
}

он удалит этот код из вашего файла сборки, если условие ложно. Вы можете увидеть рабочий пример сборки Webpack здесь.

другой способ-использовать JS файл как proxy, и пусть этот файл загружает интересующий модуль в commonjs, и экспортировать его как es2015 module, например:

// file: myModule.dev.js
module.exports = "this is in dev"

// file: myModule.prod.js
module.exports = "this is in prod"

// file: myModule.js
let loadedModule
if(WEBPACK_IS_DEVELOPMENT){
    loadedModule = require('./myModule.dev.js')
}else{
    loadedModule = require('./myModule.prod.js')
}

export const myString = loadedModule

тогда вы можете использовать модуль ES2015 в вашем приложении обычно:

// myApp.js
import { myString } from './store/myModule.js'
myString // <- "this is in dev"

Не уверен, почему " webpack.DefinePlugin " ответ является лучшим везде для определения импорта на основе среды / требует.

The при таком подходе вы все еще доставляете все эти модули клиенту - > проверьте с webpack-bundle-analyezer например. И не сокращая свой пакет.размер js вообще :)

Так что действительно работает хорошо и гораздо логичнее: NormalModuleReplacementPlugin

поэтому вместо того, чтобы делать условное требование on_client - > просто не включайте не нужные файлы в пакет в первую очередь

надеюсь, что это поможет

использовать ifdef-loader. В исходных файлах вы можете делать такие вещи, как

/// #if ENV === 'production'
console.log('production!');
/// #endif

соответствующего webpack конфигурация

const preprocessor = {
  ENV: process.env.NODE_ENV || 'development',
};

const ifdef_query = require('querystring').encode({ json: JSON.stringify(preprocessor) });

const config = {
  // ...
  module: {
    rules: [
      // ...
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: `ifdef-loader?${ifdef_query}`,
        },
      },
    ],
  },
  // ...
};

я в конечном итоге с помощью чего-то похожего на Мэтт Деррик' Ответ, но волновался по поводу двух моментов:

  1. полная конфигурация вводится каждый раз, когда я использую ENV (что плохо для больших конфигов).
  2. мне нужно определить несколько точек входа, потому что require(env) указывает на разные файлы.

то, что я придумал-это простой композитор, который строит объект конфигурации и вводит его в конфигурацию модуль.
Вот файловая структура, которую я использую для этого:

config/
 └── main.js
 └── dev.js
 └── production.js
src/
 └── app.js
 └── config.js
 └── ...
webpack.config.js

The main.js содержит все настройки по умолчанию:

// main.js
const mainConfig = {
  apiEndPoint: 'https://api.example.com',
  ...
}

module.exports = mainConfig;

The dev.js и production.js только держите конфигурационный материал, который переопределяет основную конфигурацию:

// dev.js
const devConfig = {
  apiEndPoint: 'http://localhost:4000'
}

module.exports = devConfig;

важной частью является webpack.config.js который составляет конфигурацию и использует DefinePlugin для создания переменной среды __APP_CONFIG__, который содержит в составе конфигурации объект:

const argv = require('yargs').argv;
const _ = require('lodash');
const webpack = require('webpack');

// Import all app configs
const appConfig = require('./config/main');
const appConfigDev = require('./config/dev');
const appConfigProduction = require('./config/production');

const ENV = argv.env || 'dev';

function composeConfig(env) {
  if (env === 'dev') {
    return _.merge({}, appConfig, appConfigDev);
  }

  if (env === 'production') {
    return _.merge({}, appConfig, appConfigProduction);
  }
}

// Webpack config object
module.exports = {
  entry: './src/app.js',
  ...
  plugins: [
    new webpack.DefinePlugin({
      __APP_CONFIG__: JSON.stringify(composeConfig(ENV))
    })
  ]
};

последний шаг теперь config.js, это выглядит так (используя синтаксис экспорта импорта es6 здесь, потому что его под webpack):

const config = __APP_CONFIG__;

export default config;

в своем app.js теперь вы можете использовать import config from './config'; чтобы получить объект конфигурации.

хотя это не лучшее решение, оно может работать для некоторых ваших потребностей. Если вы хотите запустить другой код в узле и браузере, используя это работало для меня:

if (typeof window !== 'undefined') 
    return
}
//run node only code now

используйте переменные окружения для создания развертываний dev и prod:

https://webpack.js.org/guides/environment-variables/