У меня есть кое-что для разработки - например, моки, которыми я не хотел бы загромождать свой файл распределенной сборки.
В RequireJS вы можете передать конфигурацию в файле плагина и условно потребовать что-то в зависимости от этого.
Для webpack, похоже, нет способа сделать это. Во-первых, чтобы создать конфигурацию времени выполнения для среды, я использовал resolve.alias, чтобы повторно указать требование в зависимости от среды, например:
// All settings.
var all = {
fish: 'salmon'
};
// `envsettings` is an alias resolved at build time.
module.exports = Object.assign(all, require('envsettings'));
Затем при создании конфигурации веб-пакета я могу динамически назначать, на какой файл envsettings
указывает (т.е. webpackConfig.resolve.alias.envsettings = './' + env
).
Однако я бы хотел сделать что-то вроде:
if (settings.mock) {
// Short-circuit ajax calls.
// Require in all the mock modules.
}
Но, очевидно, я не хочу встраивать эти фиктивные файлы, если среда не является фиктивной.
Я мог бы вручную перенаправить все эти требования в файл-заглушку, снова используя resolve.alias, но есть ли способ, который кажется менее хакерским?
Есть идеи, как я могу это сделать? Спасибо.
источник
Ответы:
Вы можете использовать плагин определения .
Я использую его, делая что-то столь же простое, как это, в вашем файле сборки веб-пакета, где
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 .
источник
env
. Глядя на этот пример, кажется, что они обрабатывают этот флаг с помощью gulp и yargs, которые не все используют."globals": { "ENV": true }
в свой .eslintrcНе уверен, почему ответ "webpack.DefinePlugin" везде является лучшим для определения импорта / требований на основе среды.
Проблема с этим подходом является то , что вы по - прежнему поставлять все эти модули для клиента -> проверить с WebPack-расслоение-analyezer , например. И вообще не уменьшая размер вашего bundle.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}`, }, }, ], }, // ... };
источник
В итоге я использовал что-то похожее на ответ Мэтта Деррика , но беспокоился о двух моментах:
ENV
(что плохо для больших конфигураций).require(env)
указывают на разные файлы.Я придумал простой композитор, который создает объект конфигурации и вставляет его в модуль конфигурации.
Вот файловая структура, которую я использую для этого:
main.js
Содержит все конфигурации по умолчанию вещи:// main.js const mainConfig = { apiEndPoint: 'https://api.example.com', ... } module.exports = mainConfig;
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, потому что он находится в веб-пакете):const config = __APP_CONFIG__; export default config;
В вашем
app.js
теперь вы можете использоватьimport config from './config';
для получения объекта конфигурации.источник
другой способ - использовать файл 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.optimize.UglifyJsPlugin()
, оптимизация webpack не будет загружать модуль, так как код строки внутри условного выражения всегда ложен, поэтому webpack удаляет его из сгенерированного пакетаСтолкнувшись с той же проблемой, что и OP, и из-за лицензирования требовалось не включать определенный код в определенные сборки, я принял webpack-conditional-loader следующим образом:
В моей команде сборки я устанавливаю переменную среды, соответствующую моей сборке. Например, demo в package.json:
... "scripts": { ... "buildDemo": "./node_modules/.bin/webpack --config webpack.config/demo.js --env.demo --progress --colors", ...
В документации, которую я читал, отсутствует запутанный момент, заключается в том, что я должен сделать это видимым на протяжении всей обработки сборки , гарантируя, что моя переменная env будет введена в глобальный процесс, таким образом, в моем webpack.config / demo.js:
/* The demo includes project/reports action to access placeholder graphs. This is achieved by using the webpack-conditional-loader process.env.demo === true */ const config = require('./production.js'); config.optimization = {...(config.optimization || {}), minimize: false}; module.exports = env => { process.env = {...(process.env || {}), ...env}; return config};
Имея это на месте, я могу условно исключить что угодно, гарантируя, что любой связанный код должным образом вытряхивается из результирующего JavaScript. Например, в моем routes.js демонстрационный контент не используется в других сборках, таким образом:
... // #if process.env.demo import Reports from 'components/model/project/reports'; // #endif ... const routeMap = [ ... // #if process.env.demo {path: "/project/reports/:id", component: Reports}, // #endif ...
Это работает с webpack 4.29.6.
источник
Я боролся с настройкой env в своих конфигурациях веб-пакетов. Обычно я хочу установить env так, чтобы его можно было достичь внутри
webpack.config.js
,postcss.config.js
а внутри самого приложения точки входа (index.js
обычно). Я надеюсь, что мои выводы могут кому-то помочь.Решение, которое я придумал, состоит в том, чтобы передать
--env production
или--env development
, а затем установить режим внутриwebpack.config.js
. Однако это не помогает мне сделатьenv
доступным там, где я хочу (см. Выше), поэтому мне также нужноprocess.env.NODE_ENV
явно указать , как рекомендуется здесь . Наиболее важная часть, которая у меня естьwebpack.config.js
ниже.... module.exports = mode => { process.env.NODE_ENV = mode; if (mode === "production") { return merge(commonConfig, productionConfig, { mode }); } return merge(commonConfig, developmentConfig, { mode }); };
источник
Используйте переменные envirnment для создания развертываний dev и prod:
https://webpack.js.org/guides/environment-variables/
источник
Хотя это не лучшее решение, оно может сработать для некоторых ваших нужд. Если вы хотите запустить другой код в узле и браузере, это сработало для меня:
if (typeof window !== 'undefined') return } //run node only code now
источник