ওয়েবপ্যাক ব্যবহার করে পরিবেশের উপর ভিত্তি করে শর্তাধীন বিল্ড


95

বিকাশের জন্য আমার কাছে কিছু জিনিস রয়েছে - উদাহরণস্বরূপ যে শখগুলি আমি আমার বিতরণ করা বিল্ড ফাইলটি ফুটিয়ে তুলতে চাই না।

আবশ্যকজেএস-এ আপনি একটি প্লাগইন ফাইলে একটি কনফিগারেশন পাস করতে পারেন এবং এর ভিত্তিতে কিছু জিনিস প্রয়োজন হয় না।

ওয়েবপ্যাকের জন্য এটি করার কোনও উপায় বলে মনে হচ্ছে না। প্রথমত পরিবেশের জন্য একটি রানটাইম কনফিগারেশন তৈরি করতে আমি পরিবেশের উপর নির্ভর করে প্রয়োজনীয়তা পুনরুদ্ধার করতে সংকল্প.আলিয়াস ব্যবহার করেছি , যেমন:

// 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.
}

তবে স্পষ্টতই আমি যদি পরিবেশগুলি উপহাস না করে তবে সেই মক ফাইলগুলি তৈরি করতে চাই না।

আমি আবার সমাধান.আলিয়াস ব্যবহার করে স্টাব ফাইলটিতে ম্যানুয়ালি এই সমস্তগুলি পুনঃসংশোধন করতে পারি - তবে কি এমন কোনও উপায় আছে যা কম মনে হচ্ছে?

কোন ধারণা আমি কীভাবে এটি করতে পারি? ধন্যবাদ


নোট করুন যে আপাতত আমি যে পরিবেশটি চাই না তার উপর একটি ফাঁকা (স্টাব) ফাইলের দিকে ইঙ্গিত করার জন্য আমি ওরফে ব্যবহার করেছি (যেমন প্রয়োজন ('মকস' প্রয়োজন)) নন-মক এনভেসিগুলিতে একটি ফাঁকা ফাইলের দিকে নির্দেশ করবে a কিছুটা হ্যাকি মনে হচ্ছে তবে এটি কাজ করে
ডমিনিক

উত্তর:


60

আপনি সংজ্ঞায়িত প্লাগইন ব্যবহার করতে পারেন ।

আমি আপনার ওয়েবপ্যাক বিল্ড ফাইলে এটির মতো সাধারণ কিছু করে এটি ব্যবহার করি যেখানে 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!');
}

শর্তটি মিথ্যা হলে এটি আপনার বিল্ড ফাইলের বাইরে এই কোডটি কেটে ফেলবে। আপনি এখানে একটি কার্যকারী ওয়েবপ্যাক বিল্ড উদাহরণ দেখতে পারেন ।


আমি এই সমাধানটি দ্বারা কিছুটা বিভ্রান্ত হয়ে পড়েছি। এটি কীভাবে সেট করার কথা ছিল তা উল্লেখ করা হয়নি env। এই উদাহরণটি দেখে মনে হচ্ছে যেন তারা এই পতাকাটি গুল্প এবং ইয়ার্গসের মাধ্যমে পরিচালনা করছে যা প্রত্যেকে ব্যবহার করছে না।
Andre

4
লিন্টারগুলির সাথে এটি কীভাবে কাজ করে? আপনার কি নতুন গ্লোবাল ভেরিয়েবলগুলি ম্যানুয়ালি সংজ্ঞায়িত করতে হবে যা ডিফাইন প্লাগইনে যুক্ত হয়?
চিহ্নিত করুন

4
হ্যাঁ। "globals": { "ENV": true }আপনার .eslintrc- এর মতো কিছু যুক্ত করুন
ম্যাট ডেরিক

আমি কীভাবে কোনও উপাদানগুলির মধ্যে ENV পরিবর্তনশীল অ্যাক্সেস করব? আমি উপরের সমাধানটি চেষ্টা করেছি কিন্তু এখনও ত্রুটি পেয়েছি যে ENV সংজ্ঞায়িত হয়নি
jasan

20
এটি বিল্ড ফাইলগুলির বাইরে কোডটি ছিনিয়ে নেবে না! আমি এটি পরীক্ষা করেছি এবং কোডটি এখানে রয়েছে।
লিওনেল

42

পরিবেশ ভিত্তিক আমদানি / প্রয়োজনীয়তা সংজ্ঞায়নের জন্য কেন "ওয়েবপ্যাক.ডাইফাইনপ্লাগিন" উত্তর সর্বত্র শীর্ষ তা নিশ্চিত নন Not

এই পদ্ধতির সাথে সমস্যাটি হ'ল আপনি এখনও সেই সমস্ত মডিউলগুলি ক্লায়েন্টের কাছে পৌঁছে দিচ্ছেন -> উদাহরণস্বরূপ ওয়েবপ্যাক-বান্ডেল-অ্যানালাইজার দিয়ে পরীক্ষা করুন । এবং আপনার বান্ডেল.জেএস এর আকার একেবারেই হ্রাস করছে না :)

সুতরাং যা সত্যিই ভাল কাজ করে এবং আরও অনেক যুক্তিযুক্ত তা হ'ল: নরমালমডিউল রিপ্লেসমেন্ট প্লাগিন

সুতরাং একটি অন-ক্লায়েন্ট শর্তাধীন প্রয়োজনের চেয়ে -> প্রথমে প্রয়োজনীয় ফাইলগুলি বান্ডলে অন্তর্ভুক্ত করবেন না

আশা করি এইটি কাজ করবে


দুর্দান্ত প্লাগইন সম্পর্কে জানতেন না!
ডোমিনিক

এই দৃশ্যের সাথে আপনার পরিবেশ প্রতি একাধিক বিল্ড হবে না? উদাহরণস্বরূপ, যদি আমার কাছে ডেভ / কিউএ / ইউএটি / উত্পাদন পরিবেশের জন্য ওয়েব পরিষেবা ঠিকানা থাকে তবে আমার তখন প্রতিটি পরিবেশের জন্য ৪ টি পৃথক পাত্রে প্রয়োজন। আদর্শভাবে আপনার কাছে একটি ধারক থাকবে এবং কোন কনফিগারটি লোড করতে হবে তা নির্দিষ্ট করতে একটি পরিবেশ ভেরিয়েবলের সাথে এটি চালু করবেন।
ব্রেট ম্যাথ

না সত্যিই না. প্লাগইনটি দিয়ে আপনি যা করছেন ঠিক এটি -> আপনি এনভ ভার্সের মাধ্যমে আপনার পরিবেশটি নির্দিষ্ট করেন এবং এটি কেবলমাত্র একটি ধারক তৈরি করে, তবে অতিরিক্ত পরিবেশের জন্য বাড়াবাড়ি ছাড়াই environment অফ কোর্স এটিও নির্ভর করে যে আপনি কীভাবে আপনার ওয়েবপ্যাক কনফিগারেশন সেটআপ করেন এবং স্পষ্টতই আপনি সমস্ত বিল্ড তৈরি করতে পারেন তার উপর নির্ভর করে তবে এই প্লাগইনটি কী এবং কী করছে তা নয়।
রোমান hyালিভ

34

ব্যবহার 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}`,
        },
      },
    ],
  },
  // ...
};

4
আমি এই উত্তরটিকে অগ্রাহ্য করেছি কারণ গ্রহণযোগ্য উত্তর প্রত্যাশার মতো কোডটি সরিয়ে দেয় না এবং প্রাক প্রসেসরের মতো সিনট্যাক্সকে শর্তযুক্ত উপাদান হিসাবে চিহ্নিত করার সম্ভাবনা বেশি থাকে।
খ্রিস্টান আইভিসেভিচ

4
অনেক ধন্যবাদ! ইহা যাদুর মত কাজ করে। কনটেক্সট্রেস রিপ্লেসমেন্ট প্লাগিন, নরমালমডিউল রিপ্লেসমেন্ট প্লাগিন এবং অন্যান্য স্টাফ সহ বেশ কয়েক ঘন্টা পরীক্ষা-নিরীক্ষা সব ব্যর্থ হয়েছিল। এবং এখানে আমার দিন বাঁচাতে ifdef- লোডার।
জেরন-ডায়োভিস

28

আমি ম্যাট ডেরিকের উত্তরের অনুরূপ কিছু ব্যবহার করে শেষ করেছি , তবে দুটি পয়েন্ট নিয়ে চিন্তিত ছিলাম:

  1. আমি যতবার ব্যবহার করি ততবার সম্পূর্ণ কনফিগার ইনজেকশন দেওয়া হয় ENV(যা বড় কনফিগারগুলির পক্ষে খারাপ)।
  2. আমাকে একাধিক এন্ট্রি পয়েন্টগুলি সংজ্ঞায়িত করতে হবে কারণ require(env)বিভিন্ন ফাইলগুলিতে পয়েন্ট রয়েছে।

আমি যা নিয়ে এসেছি তা হ'ল একটি সাধারণ সুরকার যা একটি কনফিগার অবজেক্ট তৈরি করে এবং এটি একটি কনফিগার মডিউলে সংক্রমিত করে।
Iam ফাইলের কাঠামোটি এখানে এটির জন্য ব্যবহার করছি:

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

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এটির মতো দেখাচ্ছে (এখানে এসপি আমদানি রফতানি বাক্য গঠন ব্যবহার করা হচ্ছে কারণ এটির ওয়েবপ্যাকটি এর অধীনে):

const config = __APP_CONFIG__;

export default config;

আপনার app.jsএখন আপনি import config from './config';কনফিগার বস্তু পেতে ব্যবহার করতে পারেন।


4
সত্যিই এখানে সেরা উত্তর
গ্যাব্রিয়েল

18

অন্য উপায়টি জেএস ফাইলটিকে একটি হিসাবে ব্যবহার করছে 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"

19
/ অন্য এবং প্রয়োজনীয়গুলির সাথে একমাত্র সমস্যা হ'ল উভয় প্রয়োজনীয় ফাইল উত্পন্ন ফাইলের মধ্যেই বান্ডিল হবে। আমি কোনও কাজ খুঁজে পাইনি। মূলত প্রথমে বান্ডিলিং হয়, তারপরে ম্যাংলিং।
অ্যালেক্স

4
এটি প্রয়োজনীয় নয়, আপনি যদি নিজের ওয়েবপ্যাক ফাইলটি প্লাগইন ব্যবহার করেন তবে ওয়েবপ্যাকের webpack.optimize.UglifyJsPlugin()অপ্টিমাইজেশনটি মডিউলটি লোড করবে না, কারণ শর্তাধীন অভ্যন্তরের লাইন কোডটি সর্বদা মিথ্যা, তাই ওয়েবপ্যাকটি উত্পন্ন বান্ডেল থেকে সরিয়ে ফেলবে
আলেজান্দ্রো সিলভা

@ আলেজান্দ্রোসিলভা আপনার কি এর রেপো উদাহরণ আছে?
ক্যাপচিন

4
@ থ্যাভেনজিস্ট ইয়েপ: গিথুব. com/ আলেজান্দ্রোসিলভা / মমোট্র্যাকার / ব্লব / মাস্টার / এটি নোড + রিঅ্যাক্ট + রিডিক্স পোষা প্রাইসিকে: পি
আলেজান্দ্রো সিলভা

4

ওপি-র মতো একই সমস্যার মুখোমুখি হয়েছি এবং লাইসেন্সিংয়ের কারণে, নির্দিষ্ট বিল্ডগুলিতে নির্দিষ্ট কোড অন্তর্ভুক্ত না করার কারণে আমি ওয়েবপ্যাক-শর্তসাপেক্ষ-লোডারটিকে নিম্নরূপে গ্রহণ করেছি:

আমার বিল্ড কমান্ডে আমি আমার বিল্ডের জন্য উপযুক্তভাবে পরিবেশের পরিবর্তনশীল সেট করে রেখেছি। উদাহরণ হিসাবে প্যাকেজ.জসনে 'ডেমো':

...
  "scripts": {
    ...
    "buildDemo": "./node_modules/.bin/webpack --config webpack.config/demo.js --env.demo --progress --colors",
...

আমার পড়া ডকুমেন্টেশন থেকে যে বিভ্রান্তিকর বিটটি অনুপস্থিত তা হ'ল আমার এনভ ভেরিয়েবলটি আমার ওয়েবপ্যাক.কনফিগ / ডেমো.জেজে এইভাবে বিশ্বব্যাপী প্রক্রিয়াটিতে প্রবেশ করার বিষয়টি নিশ্চিত করে বিল্ড প্রসেসিংয়ে এটি দৃশ্যমান করতে হবে :

/* 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};

এটি জায়গায় রেখে, আমি শর্তাধীন যে কোনও কোডকে ফলাফলের জাভাস্ক্রিপ্ট থেকে সঠিকভাবে ঝাঁকানো হয়েছে তা নিশ্চিত করেই বাদ দিতে পারি। উদাহরণস্বরূপ আমার রুটস.জেসে ডেমো সামগ্রীগুলি অন্য বিল্ডগুলির বাইরে রাখা হয়:

...
// #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
...

এটি ওয়েবপ্যাক 4.29.6 এর সাথে কাজ করে।


4
রয়েছে github.com/dearrrfish/preprocess-loader যা আরও বেশি বৈশিষ্ট্য আছে
user9385381

1

আমি আমার ওয়েবপ্যাক কনফিগারেশনে এনভিটি সেট করার সাথে লড়াই করেছি। কি আমি সাধারণত চাই যে এটা ভিতরে পৌঁছে যাবে তাই সেট 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 });
};

0

ডেভ এবং প্রোড মোতায়েন তৈরি করতে এনভায়ারমেন্ট ভেরিয়েবলগুলি ব্যবহার করুন:

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


4
এটি আমি যা বলছিলাম তা নয়
ডমিনিক

সমস্যাটি হ'ল ওয়েবপ্যাকটি বান্ডিলটি তৈরি করার সময় শর্তটিকে উপেক্ষা করবে এবং যেভাবেই উন্নয়নের জন্য লোডযুক্ত কোড অন্তর্ভুক্ত করবে ... সুতরাং এটি সমস্যার সমাধান করবে না
sergioviniciuss

-1

যদিও এটি সেরা সমাধান নয়, এটি আপনার কিছু প্রয়োজনের জন্য কাজ করতে পারে। আপনি যদি নোড এবং ব্রাউজারে বিভিন্ন কোড চালাতে চান তবে এটি আমার জন্য কাজ করেছে:

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

4
ওপি একটি সংকলন সময়ের সিদ্ধান্ত সম্পর্কে জিজ্ঞাসা করছে, আপনার উত্তর রান সময় সম্পর্কে।
মাইকেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.