Comments (36)
@arackaf FP is especially hard in JS because it's not strongly typed. Doing FP in Haskell or PureScript is a joy because you just need to connect the types! 😍
from customize-cra.
Now I'm wondering what was the reasoning for introducing the env parameter in react-app-rewired? (maybe @timarney can answer here)
In practice I don't think env is used much and yes it's just process.env.NODE_ENV
I would remove (if I was writing that code again).
from customize-cra.
@benedyktdryl I went with the core
naming because of this :
Also, installing @react-app-rewired/core would be enough to get started with the scripts in package.json
Also, override
would be the central nerve of this API so I wouldn't consider it a simple utility IMO. 😄
I agree with you on methods passed to override should be always executed
, I hesitated with it too. The less API surface, the better!
from customize-cra.
@arackaf Just so I'm sure about the final syntax expected, is it :
module.exports = override(
process.env.BUNDLE_VISUALIZE == 1 && addBundleVisualizer()
)
?
In this case yes we can change override
to handle the falsy case :
const { flow, curry } = require('lodash')
function override(...pipeline) {
return function(config, env) {
return flow(
...pipeline.map(f => {
+ if (f === false) {
+ return a => a
+ }
const curried = curry(f, 2)
return curried(curry.placeholder, env)
})
)(config)
}
}
from customize-cra.
Now I'm wondering what was the reasoning for introducing the env
parameter in react-app-rewired? (maybe @timarney can answer here)
Is it just a shortcut / alias for process.env.NODE_ENV
?
If we get ride of env
we could do :
const { flow } = require('lodash')
function override(...pipeline) {
return flow(...pipeline.map(f => (f === false ? a => a : f)))
}
And addX
function relying on env
could rely on process.env.NODE_ENV
directly.
from customize-cra.
I'd name ...pipeline
something more descriptive maybe. Plugins?
from customize-cra.
Gheh, that map
is actually filter(identity)
.
from customize-cra.
One thing to note if you haven't picked up on it already. People have published modules using react-app-rewire-SOME-PACKAGE . Makes it easier to find the config mods via NPM search. Also https://github.com/timarney/react-app-rewired#community-maintained-rewires
Nice touch regardless of what name the project uses in my opinion.
from customize-cra.
@jgoux - here's what I have currently, published in 0.1.0-beta5, along with a PR to allow for options to be passed to the bundle visualizer
const override = (...plugins) => config => flow(...plugins.map(f => f || (a => a)))(config);
I figured there's no need to limit it to precisely false - null
should probably work too, in case someone decides to do
process.env.BUNDLE_VISUALIZE == 1 ? addBundleVisualizer() : null
from customize-cra.
This looks awesome. Let me know if you need any help.
IMO methods passed to override
should be always executed, not passed as reference to method, so we will have always same API, means we can avoid confusion. Also I would call module with related methods utils
as core
sounds like something internal.
What do you think?
const { override } = require('@react-app-rewired/utils')
const addReactHotLoader = require('@react-app-rewired/add-react-hot-loader')
const addEmotion = require('@react-app-rewired/add-emotion')
const addBundleVisualizer = require('@react-app-rewired/add-bundle-visualizer')
module.exports = override(
addReactHotLoader() , /* no options, still, same API - we are passing result of execution */
addEmotion(), /* can have options, here none given so falling back to emotion's defaults */
addBundleVisualizer({ reportFilename: 'bundle.html' })
)
from customize-cra.
I like this a lot. I'm gonna look to make these changes later tonight, or PRs welcome if anyone's impatient :)
Using override like that will be a lot cleaner. Right now my config-overrides looks like this
module.exports = function override(config, env) {
if (process.env.BUNDLE_VISUALIZE == 1) {
addBundleVisualizer(config);
}
addDecoratorsLegacy(config, env);
disableEsLint(config, env);
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") }, config);
return config;
};
I can't get rid of all the imperative stuff, since I definitely don't want the bundle visualizer popping up every damn time, but something like this would still be a huge improvement
module.exports = function override(config, env) {
if (process.env.BUNDLE_VISUALIZE == 1) {
addBundleVisualizer(config); // <---- should probably make these methods able to be called directly
}
return override(
addDecoratorsLegacy(),
disableEsLint(),
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") })
)
};
Or should we be stricter and just do
module.exports = function override(config, env) {
if (process.env.BUNDLE_VISUALIZE == 1) {
override(addBundleVisualizer());
}
return override(
addDecoratorsLegacy(),
disableEsLint(),
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") })
)
};
IMO methods passed to override should be always executed, not passed as reference to method, so we will have always same API
That seems reasonable - any disagreements there?
from customize-cra.
You could also pass a lambda, as override
takes (config, [env]) => config
functions.
module.exports = override(
config => process.env.BUNDLE_VISUALIZE == 1 ? addBundleVisualizer(config) : config,
addDecoratorsLegacy(),
disableEsLint(),
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") })
)
from customize-cra.
Oh - I like that a lot. Thanks!
from customize-cra.
Hey - great stuff - thanks a ton. Version 0.1.0-beta3 is out, with the override above, working.
Only slight hiccup is the conditional application of the bundle visualizer. Would love to hear thoughts there. As far as I can tell, my only choices are to break the API for that specific plugin, or else live with the double invocation.
const { override, addDecoratorsLegacy, disableEsLint, addBundleVisualizer, addWebpackAlias } = require("customize-cra");
const path = require("path");
module.exports = override(
addDecoratorsLegacy(),
disableEsLint(),
config => (process.env.BUNDLE_VISUALIZE == 1 ? addBundleVisualizer()(config) : config),
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") })
);
from customize-cra.
I think the API is simple enough that way.
For more complicated / custom cases, I'd expect the users to write their own function for clarity :
const { override, addDecoratorsLegacy, disableEsLint, addBundleVisualizer, addWebpackAlias } = require("customize-cra");
const path = require("path");
module.exports = override(
addDecoratorsLegacy(),
disableEsLint(),
customAddBundleVisualizer,
addWebpackAlias({ ["ag-grid-react$"]: path.resolve(__dirname, "src/shared/agGridWrapper.js") })
);
function customAddBundleVisualizer(config) {
return process.env.BUNDLE_VISUALIZE == 1 ? addBundleVisualizer()(config) : config
}
IMO it's better to provide one simple way for composing the "addX" functions and let the users build on top of it if needed.
We could provide a few helpers for most common cases but I'm not sure if it's a good idea :
module.exports = override(
cond(isProduction, addBundleVisualizer()),
// in your case
cond(() => process.env.BUNDLE_VISUALIZE == 1, addBundleVisualizer())
)
function cond(test, success, failure = config => config) {
return (config, env) =>
test(config, env) ? success(config, env) : failure(config, env)
}
function isProduction(_, env) {
return env === 'production'
}
from customize-cra.
While API should be minimal, I think this is quite good to have small utils like @jgoux provided.
I remember there is existing library for operating on Webpack config. Maybe we should allow / make easier to use it or provide similar API for Webpack/Babel configuration handling?
from customize-cra.
@jgoux I'm happy enough with things as they are, but this tweet
https://twitter.com/stevenlangbroek/status/1047452160185815041
did make me wonder if we couldn't do better, for free. Couldn't override
just detect the return value of
return curried(curry.placeholder, env);
and if it's a function, surmise that something like the above has happened, and then just call it again to get the true return value?
from customize-cra.
That's not what I was thinking, but it's a whole lot better. Good stuff - thanks.
from customize-cra.
That seems reasonable, and much nicer. Hopefully Tim can let us know if we're missing something
from customize-cra.
That seems reasonable.
@jgoux you forgot to call the result of flow
with config, but yeah - that'll be great if there's no good reason to keep env around.
from customize-cra.
Lol nevermind. Read -> Post.
from customize-cra.
@StevenLangbroek thanks a ton for those fp suggestions. Not sure why you deleted them. I'll repost here, unless you really want them gone - I hope not though - I definitely plan to go over this closely.
// deleted per comment below
from customize-cra.
Thanks a ton. This is really coming together!
from customize-cra.
That seems reasonable.
@jgoux you forgot to call the result of
flow
with config, but yeah - that'll be great if there's no good reason to keep env around.
flow(...plugins)
returns a function taking parameters, and pass them to the first plugin in the pipeline. So no need to pass the config in this case as it will be provided by react-app-rewired
! 👍
As for registering the organization, it's a whole new world for me as well... But I'm sure we can find the right way together! ✌️
from customize-cra.
@arackaf because the code is wrong. My snippet ends up with an array of return values from map(applyPlugin(config))
, which I doubt is what needs to happen. @jgoux's code is correct, it just took me a while to realize I'd been looking at it wrong.
from customize-cra.
I had a similar experience (code deleted from comment)
fp is hella hard when you're not used to it. Even when you are, it seems :)
from customize-cra.
@arackaf @jgoux This project seems promising! 👍 Would love to contribute to it!
Some thoughts,
- The idea of an independent
@react-app-rewired/core
seems better than depending on the originalreact-app-rewired
for scripts. Sincereact-app-rewired
is not going to be maintained or might have legacy code, we shouldn't be depending on it. - To support multiple version of rewiring (older & future) maybe we allow imports like
@react-app-rewired/core/v2
and@react-app-rewired/core/vX
.
This way we can support multiple versions ofCRA
. - The plugins can get a version number param based on which they customize wiring if needed for various versions
from customize-cra.
@viral-sh hm - well like you said, react-app-rewired is not really maintained.
I'd say that if CRA ever changes so deeply that the old (react-app-rewired) code no longer works, then at that time we'll definitely have to make some changes, either here, or in the rewired codebase if Time will allow someone to take the project over.
For now though I'd be keen on keeping things as simple as possible.
That said, if you're wanting to help contribute, there's all sorts of new features that could be added: overriding eslint configuration (rather than just turning it off), and, well, anything else people might want - there seems to be a crap-ton of neighboring plugins listed in the rewired docs.
from customize-cra.
Some of the pre-existing plugins made for react-app-rewired may expect and rely on the env
argument. I think customize-cra should still pass process.env.NODE_ENV
to its override
plugins, just in case someone wants to use an already published plugin that needs env
. New plugins can be written to omit and ignore the env
argument, so new code will be cleaner, but backward compatibility would still be retained.
from customize-cra.
Also, this comment above proposed that falsy plugins should be ignored by override
. I agree, but the given code patch matches only false
values, whereas falsy values would include anything not considered true in an if
condition, including 0
, ""
, null
, and undefined
.
The code to check this should simply be:
if (!f) { ...
from customize-cra.
@svicalifornia Tim himself said we could safely get rid of the env argument, and let plugins just reference process.env as needed. Backward compat isn't really a concern here, since the react-app-rewired plugins don't really work with CRA 2 any, which is why this project exists.
The final code wound up ignoring any falsy values at all, as you proposed
https://github.com/arackaf/customize-cra/blob/master/index.js#L72
from customize-cra.
Yes, I saw Tim’s comment, and we all agree that new plugins will look cleaner without the env
argument. However, you could still pass the old env
argument in, and new plugins that don’t need it will just ignore it. (It’s perfectly legal in JavaScript to pass two arguments to a function which only takes one argument.)
If you really want a clean break from all of the old plugins, or at least to force them to update to work with customize-cra, then you can leave this as is. I just thought there was a chance that this new override
syntax would get added to the next version of react-app-rewired, and if so, then it should pass env
to each plugin to support the plugins that rely on that argument. (Again, any plugins that only take config
can still be called with both args and will just ignore the second arg.)
from customize-cra.
It’s perfectly legal in JavaScript to pass two arguments to a function which only takes one argument.
Understood, it just simplified the override code quite a bit. And again, the assumption was that just about none of the old plugins would work anyway, so they'd already need to be re-written.
from customize-cra.
Also given 2.0 CRA people should expect breaking changes so it's a good time for that change.
from customize-cra.
That's all fine. Plugins can be updated to use process.env.NODE_ENV
when they are updated for CRA 2.0.
However, I hope plugin authors don't split each plugin into separate CRA1 and CRA2 builds. Some app projects may need to stay on CRA1 for a while (especially if they already made webpack customizations with react-app-rewired), and it would be nice if plugins could be "universal" — automatically detect the CRA version and apply the appropriate webpack config changes.
If each plugin splits into separate CRA1 and CRA2 artifacts in npm, it will make a mess of the package namespace, and further scare a lot of companies (including some of my clients) away from a rewired approach, given that many are already apprehensive about leaving the safe confines of CRA.
from customize-cra.
Closing this - but if anyone else has inputs here, feel free.
from customize-cra.
Related Issues (20)
- __webpack_require__(...) is not a function
- CRA v4 switch from GenerateSW to InjectManifest not supported - workaround
- Is this project unmaintained? anybody here? HOT 1
- Example of "addWebpackExternals" has a error HOT 1
- 啥时候更新webpack5
- how can I prevent build/service-worker.js from being generated. I don't want any caching. please help, urgent
- add graphql loader
- create-react-app 强制更新到了 5.0.0 ,启用的是 webpack5,在配置 less 的时候出现错误 postcss Loader has been initialized using an options object that does not match the API schema,影响项目开展,望修复 HOT 12
- Incompatible with Create-React-App 5.0: Invalid Options for PostCSS Loader HOT 8
- PostCSS plugin autoprefixer requires PostCSS 8.
- options has an unknown property 'plugins' HOT 1
- useEslintRc ERROR!! HOT 1
- addWebpackExternals: react is not defined HOT 2
- Using customizers for jest configuration HOT 3
- addPostcssPlugins doesn't work when react-scripts's version higher than or equal to 5.0.0 HOT 5
- setWebpackPublicPath auto option HOT 1
- Workbox strategies uncaught no-response
- TypeError: addWebpackPlugin is not a function
- react项目:在configoveride.js中addPostcssPlugins添加postcss-pxtorem无效 HOT 7
- getBabelLoader().options is undefined when you fix babel-loader
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from customize-cra.