J'ai certaines choses à développer - par exemple des mocs avec lesquels j'aimerais ne pas gonfler mon fichier de construction distribué.
Dans RequireJS, vous pouvez passer une configuration dans un fichier de plug-in et, de manière conditionnelle, exiger des choses basées sur cela.
Pour WebPack, cela ne semble pas être une façon de faire. Tout d’abord, pour créer une configuration d’exécution pour un environnement que j’ai utilisé resol.alias , pour republier une exigence en fonction de l’environnement, par exemple:
// All settings.
var all = {
fish: 'salmon'
};
// `envsettings` is an alias resolved at build time.
module.exports = Object.assign(all, require('envsettings'));
Ensuite, lors de la création de la configuration webpack, je peux attribuer dynamiquement le fichier vers lequel pointe envsettings
(c.-à-d. webpackConfig.resolve.alias.envsettings = './' + env
).
Cependant, j'aimerais faire quelque chose comme:
if (settings.mock) {
// Short-circuit ajax calls.
// Require in all the mock modules.
}
Mais évidemment, je ne veux pas intégrer ces fichiers fictifs si l'environnement n'est pas fictif.
Je pourrais éventuellement redéfinir manuellement tous ces éléments nécessaires sur un fichier de raccord en utilisant resol.alias à nouveau - mais y a-t-il un moyen de se sentir moins hacky?
Des idées comment je peux faire ça? Merci.
Vous pouvez utiliser le define plugin .
Je l'utilise en faisant quelque chose d'aussi simple que cela dans votre fichier de compilation webpack où env
est le chemin d'accès à un fichier qui exporte un objet de paramètres:
// 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 };
et puis cela dans votre code
if (ENV.debug) {
console.log('Yo!');
}
Il supprimera ce code de votre fichier de construction si la condition est fausse. Vous pouvez voir un travail exemple de construction Webpack ici .
Vous ne savez pas pourquoi la réponse "webpack.DefinePlugin" est la meilleure pour la définition des importations/exigences basées sur l'environnement.
Le problème avec cette approche est que vous livrez toujours tous ces modules au client -> vérifier avec webpack-bundle-analyezer = par exemple. Et ne pas réduire la taille de votre bundle.js :)
Donc, ce qui fonctionne vraiment bien et de manière beaucoup plus logique est: NormalModuleReplacementPlugin
Donc, plutôt que de faire un on_client conditionnel exiger -> tout simplement pas inclure les fichiers non nécessaires à la bundle en premier lieu
J'espère que ça t'as aidé
Utilisation ifdef-loader
. Dans vos fichiers source, vous pouvez faire des choses comme
/// #if ENV === 'production'
console.log('production!');
/// #endif
La configuration appropriée de webpack
est
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}`,
},
},
],
},
// ...
};
J'ai fini par utiliser quelque chose de similaire à Réponse de Matt Derrick , mais je craignais deux points:
ENV
(ce qui est mauvais pour les grandes configurations).require(env)
pointe sur des fichiers différents.Ce que je propose est un simple composer) qui construit un objet de configuration et l'injecte dans un module de configuration.
Voici la structure de fichier qu'Iam utilise pour cela:
config/
└── main.js
└── dev.js
└── production.js
src/
└── app.js
└── config.js
└── ...
webpack.config.js
Le main.js
contient tous les éléments de configuration par défaut:
// main.js
const mainConfig = {
apiEndPoint: 'https://api.example.com',
...
}
module.exports = mainConfig;
Le dev.js
et production.js
ne contient que des éléments de configuration qui remplacent la configuration principale:
// dev.js
const devConfig = {
apiEndPoint: 'http://localhost:4000'
}
module.exports = devConfig;
La partie importante est le webpack.config.js
qui compose la configuration et utilise le DefinePlugin pour générer une variable d’environnement __APP_CONFIG__
qui contient l’objet config composé:
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))
})
]
};
La dernière étape est maintenant le config.js
, cela ressemble à ceci (Utilisation de la syntaxe importation importation es6 ici car elle se trouve sous Webpack):
const config = __APP_CONFIG__;
export default config;
Dans votre app.js
vous pouvez maintenant utiliser import config from './config';
pour obtenir l'objet config.
une autre méthode consiste à utiliser un fichier JS en tant que proxy
et à laisser ce fichier charger le module qui vous intéresse dans commonjs
et à l'exporter en tant que es2015 module
, comme ça:
// 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
Ensuite, vous pouvez utiliser le module ES2015 dans votre application normalement:
// myApp.js
import { myString } from './store/myModule.js'
myString // <- "this is in dev"
Confronté au même problème que le PO et obligé, pour des raisons de licence, à ne pas inclure certains codes dans certaines versions, j’ai adopté le webpack-conditionitional-loader comme suit:
Dans ma commande de construction, je définis une variable d'environnement appropriée pour ma construction. Par exemple 'demo' dans package.json:
...
"scripts": {
...
"buildDemo": "./node_modules/.bin/webpack --config webpack.config/demo.js --env.demo --progress --colors",
...
Le peu de confusion qui manque dans la documentation que j'ai lue est que je dois rendre cela visible tout au long du traitement de la construction en veillant à ce que ma variable env soit injectée dans le fichier. processus global ainsi dans mon 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};
Cela mis en place, je peux sous condition exclure quoi que ce soit, en veillant à ce que tout code associé soit correctement évincé du code JavaScript résultant. Par exemple, dans le fichier routes.js, le contenu de la démo est conservé en dehors des versions suivantes:
...
// #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
...
Cela fonctionne avec webpack 4.29.6.
J'ai eu du mal à définir env dans mes configs de webpack. Ce que je veux généralement, c’est de régler env pour pouvoir l’atteindre à l'intérieur de webpack.config.js
, postcss.config.js
et à l'intérieur de l'application de point d'entrée elle-même (index.js
généralement). J'espère que mes découvertes peuvent aider quelqu'un.
La solution que j’ai trouvée est de passer en --env production
ou --env development
, puis définissez le mode dans webpack.config.js
. Cependant, cela ne m'aide pas à rendre env
accessible où je le veux (voir ci-dessus), je dois donc aussi définir process.env.NODE_ENV
explicitement, comme recommandé ici . La partie la plus pertinente que j'ai dans webpack.config.js
Suivre ci-dessous.
...
module.exports = mode => {
process.env.NODE_ENV = mode;
if (mode === "production") {
return merge(commonConfig, productionConfig, { mode });
}
return merge(commonConfig, developmentConfig, { mode });
};
Bien que ce ne soit pas la meilleure solution, cela peut répondre à certains de vos besoins. Si vous souhaitez exécuter un code différent dans le noeud et le navigateur à l'aide de cette méthode a fonctionné pour moi:
if (typeof window !== 'undefined')
return
}
//run node only code now
Utilisez des variables d'environnement pour créer des déploiements de dev et de prod: