GithubHelp home page GithubHelp logo

Comments (36)

jgoux avatar jgoux commented on August 16, 2024 3

@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.

timarney avatar timarney commented on August 16, 2024 2

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).

https://github.com/timarney/react-app-rewired/blob/master/packages/react-app-rewired/scripts/start.js

from customize-cra.

jgoux avatar jgoux commented on August 16, 2024 1

@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.

jgoux avatar jgoux commented on August 16, 2024 1

@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.

jgoux avatar jgoux commented on August 16, 2024 1

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.

StevenLangbroek avatar StevenLangbroek commented on August 16, 2024 1

I'd name ...pipeline something more descriptive maybe. Plugins?

from customize-cra.

StevenLangbroek avatar StevenLangbroek commented on August 16, 2024 1

Gheh, that map is actually filter(identity).

from customize-cra.

timarney avatar timarney commented on August 16, 2024 1

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.

arackaf avatar arackaf commented on August 16, 2024 1

@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.

benedyktdryl avatar benedyktdryl commented on August 16, 2024

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.

arackaf avatar arackaf commented on August 16, 2024

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.

jgoux avatar jgoux commented on August 16, 2024

@arackaf

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.

arackaf avatar arackaf commented on August 16, 2024

Oh - I like that a lot. Thanks!

from customize-cra.

arackaf avatar arackaf commented on August 16, 2024

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.

jgoux avatar jgoux commented on August 16, 2024

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.

benedyktdryl avatar benedyktdryl commented on August 16, 2024

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.

arackaf avatar arackaf commented on August 16, 2024

@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.

arackaf avatar arackaf commented on August 16, 2024

That's not what I was thinking, but it's a whole lot better. Good stuff - thanks.

from customize-cra.

arackaf avatar arackaf commented on August 16, 2024

That seems reasonable, and much nicer. Hopefully Tim can let us know if we're missing something

from customize-cra.

arackaf avatar arackaf commented on August 16, 2024

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.

StevenLangbroek avatar StevenLangbroek commented on August 16, 2024

Lol nevermind. Read -> Post.

from customize-cra.

arackaf avatar arackaf commented on August 16, 2024

@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.

arackaf avatar arackaf commented on August 16, 2024

Thanks a ton. This is really coming together!

from customize-cra.

jgoux avatar jgoux commented on August 16, 2024

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.

StevenLangbroek avatar StevenLangbroek commented on August 16, 2024

@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.

arackaf avatar arackaf commented on August 16, 2024

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.

viral-sh avatar viral-sh commented on August 16, 2024

@arackaf @jgoux This project seems promising! 👍 Would love to contribute to it!

Some thoughts,

  1. The idea of an independent @react-app-rewired/core seems better than depending on the original react-app-rewired for scripts. Since react-app-rewired is not going to be maintained or might have legacy code, we shouldn't be depending on it.
  2. 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 of CRA.
  3. The plugins can get a version number param based on which they customize wiring if needed for various versions

from customize-cra.

arackaf avatar arackaf commented on August 16, 2024

@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.

svicalifornia avatar svicalifornia commented on August 16, 2024

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.

svicalifornia avatar svicalifornia commented on August 16, 2024

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.

arackaf avatar arackaf commented on August 16, 2024

@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.

svicalifornia avatar svicalifornia commented on August 16, 2024

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.

arackaf avatar arackaf commented on August 16, 2024

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.

timarney avatar timarney commented on August 16, 2024

Also given 2.0 CRA people should expect breaking changes so it's a good time for that change.

from customize-cra.

svicalifornia avatar svicalifornia commented on August 16, 2024

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.

arackaf avatar arackaf commented on August 16, 2024

Closing this - but if anyone else has inputs here, feel free.

from customize-cra.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.