Development Tip

Webpack을 사용하는 환경 기반 조건부 빌드

yourdevel 2020. 10. 9. 12:29
반응형

Webpack을 사용하는 환경 기반 조건부 빌드


개발을위한 몇 가지 사항이 있습니다. 예를 들어 분산 된 빌드 파일을 부 풀리지 않으려는 모의 작업이 있습니다.

RequireJS에서는 플러그인 파일에 구성을 전달할 수 있으며이를 기반으로 조건부로 요구할 수 있습니다.

웹팩의 경우이 작업을 수행하는 방법이없는 것 같습니다. 먼저 환경에 대한 런타임 구성을 만들기 위해 resolve.alias사용 하여 환경에 따라 요구 사항 을 다시 지정했습니다. 예 :

// 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.alias를 사용하여 필요한 모든 것을 스텁 파일로 수동으로 다시 가리킬 수 있지만 덜 험난하다고 느끼는 방법이 있습니까?

어떻게 할 수 있습니까? 감사.


define 플러그인을 사용할 수 있습니다 .

env설정 개체를 내보내는 파일의 경로 인 webpack 빌드 파일에서 다음과 같이 간단한 작업을 수행하여 사용합니다 .

// 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 빌드 예제를 볼 수 있습니다 .


"webpack.DefinePlugin"답변이 환경 기반 가져 오기 / 요구 사항을 정의하는 모든 곳에서 가장 높은 이유를 잘 모르겠습니다.

접근 방식 문제점 은 여전히 ​​모든 모듈을 클라이언트에 제공하고 있다는 것 입니다. 예를 들어 webpack-bundle-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}`,
        },
      },
    ],
  },
  // ...
};

나는 Matt Derrick 'Answer 와 비슷한 것을 사용 했지만 두 가지 점에 대해 걱정했습니다.

  1. 전체 구성은 내가 사용할 때마다 주입됩니다 ENV(대규모 구성에는 좋지 않음).
  2. require(env)다른 파일을 가리 키기 때문에 여러 진입 점을 정의해야 합니다.

내가 생각 해낸 것은 구성 개체를 만들고 구성 모듈에 주입하는 간단한 작곡가입니다.
다음은 파일 구조입니다.

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.jsproduction.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이며 다음과 같습니다 (webpack 아래에 있으므로 여기에서 es6 가져 오기 내보내기 구문 사용).

const config = __APP_CONFIG__;

export default config;

당신에 app.js당신은 지금 사용할 수 import config from './config';는 config 객체를 얻을 수 있습니다.


another way is using a JS file as a proxy, and let that file load the module of interest in commonjs, and export it as es2015 module, like this:

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

Then you can use ES2015 module in your app normally:

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

Faced with the same problem as the OP and required, because of licensing, not to include certain code in certain builds, I adopted the webpack-conditional-loader as follows:

In my build command I set an environment variable appropriately for my build. For example 'demo' in package.json:

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

The confusing bit that is missing from the documentation I read is that I have to make this visible throughout the build processing by ensuring my env variable gets injected into the process global thus in my 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};

With this in place, I can conditionally exclude anything, ensuring that any related code is properly shaken out of the resulting JavaScript. For example in my routes.js the demo content is kept out of other builds thus:

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

This works with webpack 4.29.6.


I've struggled with setting env in my webpack configs. What I usually want is to set env so that it can be reached inside webpack.config.js, postcss.config.js and inside the entry point application itself (index.js usually). I hope that my findings can help someone.

The solution that I've come up with is to pass in --env production or --env development, and then set mode inside webpack.config.js. However, that doesn't help me with making env accessible where I want it (see above), so I also need to set process.env.NODE_ENV explicitly, as recommended here. Most relevant part that I have in webpack.config.js follow below.

...
module.exports = mode => {
  process.env.NODE_ENV = mode;

  if (mode === "production") {
    return merge(commonConfig, productionConfig, { mode });
  }
  return merge(commonConfig, developmentConfig, { mode });
};

While this is not the best solution, it may work for some of your needs. If you want to run different code in node and browser using this worked for me:

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

Use envirnment variables to create dev and prod deployments:

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

참고URL : https://stackoverflow.com/questions/28572380/conditional-build-based-on-environment-using-webpack

반응형