Mam kilka rzeczy do rozwoju - np. Makiety, którymi nie chciałbym nadużywać mojego dystrybuowanego pliku kompilacji.
W RequireJS możesz przekazać konfigurację w pliku wtyczki i warunkowo wymagać jej wprowadzenia.
Wydaje się, że w przypadku pakietu webpack nie ma sposobu, aby to zrobić. Po pierwsze, aby utworzyć konfigurację środowiska uruchomieniowego dla środowiska, użyłem solution.alias do zmiany wymagania w zależności od środowiska, np .:
// All settings.
var all = {
fish: 'salmon'
};
// `envsettings` is an alias resolved at build time.
module.exports = Object.assign(all, require('envsettings'));
Następnie podczas tworzenia konfiguracji webpacka mogę dynamicznie przypisać, który plik envsettings
wskazuje (tj webpackConfig.resolve.alias.envsettings = './' + env
.).
Chciałbym jednak zrobić coś takiego:
if (settings.mock) {
// Short-circuit ajax calls.
// Require in all the mock modules.
}
Ale oczywiście nie chcę budować w tych pozorowanych plikach, jeśli środowisko nie jest fałszywe.
Mógłbym prawdopodobnie ręcznie zmienić wszystkie te wymagania w pliku pośredniczącym, używając ponownie funkcji solution.alias - ale czy istnieje sposób, który wydaje się mniej hakerski?
Jakieś pomysły, jak mogę to zrobić? Dzięki.
źródło
Odpowiedzi:
Możesz użyć wtyczki Definiuj .
Używam go, robiąc coś tak prostego, jak to w pliku kompilacji pakietu internetowego, gdzie
env
jest ścieżka do pliku, który eksportuje obiekt ustawień:// 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 };
a potem to w swoim kodzie
if (ENV.debug) { console.log('Yo!'); }
Usunie ten kod z pliku kompilacji, jeśli warunek jest fałszywy. Tutaj możesz zobaczyć działający przykład kompilacji pakietu Webpack .
źródło
env
. Patrząc na ten przykład, wydaje się, że obsługują tę flagę za pomocą łyków i yargów, których nie wszyscy używają."globals": { "ENV": true }
do swojego .eslintrcNie jestem pewien, dlaczego odpowiedź „webpack.DefinePlugin” jest najważniejsza wszędzie przy definiowaniu importu / wymagań opartych na środowisku.
Problem z tego podejścia jest to, że są nadal dostarczając wszystkie te moduły do klienta -> sprawdzić z WebPACK-bundle-analyezer na przykład. I wcale nie zmniejszając rozmiaru pliku bundle.js :)
Więc to, co naprawdę działa dobrze i znacznie bardziej logiczne, to: NormalModuleReplacementPlugin
Więc zamiast wykonywać warunkowe wymaganie on_client -> po prostu nie dołączaj niepotrzebnych plików do pakietu w pierwszej kolejności
Mam nadzieję, że to pomoże
źródło
Użyj
ifdef-loader
. W swoich plikach źródłowych możesz robić takie rzeczy jak/// #if ENV === 'production' console.log('production!'); /// #endif
Odpowiednia
webpack
konfiguracja toconst 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}`, }, }, ], }, // ... };
źródło
Skończyło się na tym, że użyłem czegoś podobnego do odpowiedzi Matta Derricka , ale martwiłem się o dwa punkty:
ENV
(co jest złe w przypadku dużych konfiguracji).require(env)
wskazuje na różne pliki.To, co wymyśliłem, to prosty kompozytor, który buduje obiekt konfiguracyjny i wstrzykuje go do modułu konfiguracyjnego.
Oto struktura plików, której używam do tego:
main.js
Posiada wszystkie Domyślne rzeczy:// main.js const mainConfig = { apiEndPoint: 'https://api.example.com', ... } module.exports = mainConfig;
dev.js
Iproduction.js
tylko chwyt config rzeczy, które nadpisuje główny config:// dev.js const devConfig = { apiEndPoint: 'http://localhost:4000' } module.exports = devConfig;
Ważną częścią jest ta,
webpack.config.js
która komponuje konfigurację i używa DefinePlugin do wygenerowania zmiennej środowiskowej,__APP_CONFIG__
która przechowuje złożony obiekt konfiguracyjny: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)) }) ] };
Ostatnim krokiem jest teraz
config.js
, wygląda to tak (Używając tutaj składni importu eksportu es6, ponieważ znajduje się w pakiecie internetowym):const config = __APP_CONFIG__; export default config;
W swoim
app.js
możesz teraz użyć,import config from './config';
aby pobrać obiekt konfiguracyjny.źródło
innym sposobem jest użycie pliku JS jako a
proxy
i pozwolenie temu plikowi załadować moduł, który nas interesujecommonjs
, i wyeksportować go jakoes2015 module
, na przykład:// 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
Następnie możesz normalnie używać modułu ES2015 w swojej aplikacji:
// myApp.js import { myString } from './store/myModule.js' myString // <- "this is in dev"
źródło
webpack.optimize.UglifyJsPlugin()
optymalizacja webpacka nie załaduje modułu, ponieważ kod linii wewnątrz warunku jest zawsze fałszywy, więc webpack usuwa go z wygenerowanego pakietuW obliczu tego samego problemu co OP i wymaganego, ze względu na licencję, aby nie włączać określonego kodu w niektórych kompilacjach, zaadaptowałem program ładujący pakiet warunkowy w następujący sposób:
W poleceniu kompilacji ustawiam zmienną środowiskową odpowiednio do mojej kompilacji. Na przykład „demo” w pliku package.json:
... "scripts": { ... "buildDemo": "./node_modules/.bin/webpack --config webpack.config/demo.js --env.demo --progress --colors", ...
Mylący fragment, którego brakuje w dokumentacji, którą czytam, polega na tym , że muszę pokazać to podczas przetwarzania kompilacji , upewniając się, że moja zmienna env zostanie wstrzyknięta do procesu globalnego, a zatem w moim 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};
Mając to na swoim miejscu, mogę warunkowo wykluczyć wszystko, upewniając się, że każdy powiązany kod zostanie odpowiednio usunięty z wynikowego kodu JavaScript. Na przykład w moim pliku route.js zawartość demonstracyjna jest chroniona przed innymi kompilacjami, w ten sposób:
... // #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 ...
Działa to z pakietem webpack 4.29.6.
źródło
Zmagałem się z ustawieniem env w moich konfiguracjach webpack. Co ja zwykle chcą, aby ustawić env jest tak, że może on zostać osiągnięty w środku
webpack.config.js
,postcss.config.js
jak i wewnątrz samej aplikacji punktu wejścia (index.js
zwykle). Mam nadzieję, że moje odkrycia mogą komuś pomóc.Rozwiązaniem, które wymyśliłem, jest przekazanie
--env production
lub--env development
, a następnie ustawienie trybu wewnątrzwebpack.config.js
. Jednak to nie pomaga mi wenv
udostępnianiu tego, gdzie chcę (patrz powyżej), więc muszę również ustawićprocess.env.NODE_ENV
jawnie, zgodnie z zaleceniami tutaj . Najważniejsza część, którą mamwebpack.config.js
poniżej, znajduje się poniżej.... module.exports = mode => { process.env.NODE_ENV = mode; if (mode === "production") { return merge(commonConfig, productionConfig, { mode }); } return merge(commonConfig, developmentConfig, { mode }); };
źródło
Użyj zmiennych środowiskowych, aby utworzyć wdrożenia deweloperskie i produkcyjne:
https://webpack.js.org/guides/environment-variables/
źródło
Chociaż nie jest to najlepsze rozwiązanie, może zadziałać w przypadku niektórych Twoich potrzeb. Jeśli chcesz uruchomić inny kod w węźle i przeglądarce, to zadziałało dla mnie:
if (typeof window !== 'undefined') return } //run node only code now
źródło