-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make ramda more modular #1505
Comments
|
That's the point. 👍 |
👍 We've discussed this before, but no one's gotten around to doing it. It should just be a matter of how the NPM package is built. @luizbills: Do you feel up to taking a swing at it? |
This allows custom builds easy. Ramda is very big. Hardly ever someone will use the entire library. |
Any thoughts on converting to ES6 modules and using rollup? Tree-shaking Ramda with rollup would be amazing. |
@Hypercubed: Could you describe the advantages? I haven't tried Although it's not well-documented, it's fairly simple to build your own version of Ramda right now. This doesn't start with static analysis of a codebase, though, but with a list of public functions you want to include. The build does the recursive dependency management and builds as small a package as possible. |
Using ES6 modules would improve static analysis of the code base.... something that is difficult with CJS modules. On your end Rollup would do pretty much what you described... take an index file and build the smallest a package as possible (maybe replacing your build script). I guess the advantage of using ES6 modules would be to allow users to do tree shaking on their end. They can import ramda methods individually, without the need to know the internal paths, then use rollup tree shaking to get a minimal build. For example in my project I can do:
to get only the relevant portions of the ramda codebase. Because Ramda is already pretty modular it's probably not to hard to convert to ES6 modules. The hard part would be converting the build process. |
I don't think it would be hard to write a new build process to handle that. It would clearly work fine for browser usage. Even there, I have concerns about readability. I think of ramda.js as our flagship output. As much as possible, I would like that to remain as clean and readable, and as much like hand-crafted code as possible. But it's not at all clear that this would work for Node users. Right now Node users can use the same file that browser users do, and they can also import individual functions directly. (There is an unfortunate 'src' in the import path, but we can straighten that out..) If we switched to ES6 modules, would Node users would presumably have to run some build step before using the individual imports, and that seems to bad. |
Perhaps a feature branch could be started for the ES6 import. That way when it becomes the de facto it won't be but a hop skip and a jump for Ramda. Also, users who are just plain desperate for it right now would be able to clone from that branch. I've proposed ES6 modules before, for the same reason @Hypercubed has. Perhaps we could tag team? I think also with the rapidity that javascript is evolving it is probably going to be necessary to incorporate a transpilation step at some point. Hand crafted code is the best, but transpiled code would allow ramda to support a wider range. Also, ES6 support could help Ramda dramatically improve other areas such as error handling. |
I was messing around with ES modules in Ramda the other day, so I figured I'd push a branch up that people can experiment with: https://github.com/scott-christopher/ramda/tree/es-modules Note: this is just a experiment, with no guarantees it will eventuate into anything The UMD module generated by rollup is surprisingly not far off what the current Ramda build script produces: https://github.com/scott-christopher/ramda/blob/es-modules/dist/ramda-rollup.js @CrossEye's point about continuing support for importing individual modules in commonjs environments still stands, meaning if we were to go down this path we would need to look into deploying separate packages to NPM to support both module types. That could be a good opportunity to solve for being able to import individual modules in commonjs environments while we're poking at it. |
You're right! This is good to see. :) |
@scott-christopher: This is great! I'd love to be using external tools for this rather than maintaining our own. All kudos to @davidchambers, whose script was much better than the one I was building, but I'd still rather work with a tool that's well-maintained, if it does as good a job as this. |
@scott-christopher It looks great. What else needs to be done? Might also consider adding Babel to the mix to allow proper ES6 code. |
Hi guys, this is really great! I just want to add that its possible to add to @scott-christopher es-modules branch the following steps:
Check out Redux as example. They develop with es6 features so they use additional babel plugins for the transpilation. The benefits are (you mentioned almost all of them):
I just started using ramda and its awesome ! BTW, babel-plugin-ramda (I made PR which adds babel 6 support) is a workaround for guys using babel in their build but it will be great to have it out of the box. |
The holidays intervened and everyone got distracted by shiny new things, but we really should get back to this. This would be a fantastic improvement. I suppose we need to keep backward compatibility with @scott-christopher: What do you think about trying to merge this for v0.20.0? |
@borisirota suggestions sound like a good approach. I'll see if I can spend some time on it this afternoon. |
I've updated my branch with the latest changes from master and made the changes suggested by @borisirota, though babel unfortunately adds a bit of unnecessary cruft to the generated commonjs modules (see example below), so I ended up just creating a simple shell script to do the transformation instead which can be run via https://github.com/scott-christopher/ramda/blob/es-modules/scripts/build-commonjs Below is an example of the babel-generated 'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _curry = require('./internal/_curry2.js');
var _curry3 = _interopRequireDefault(_curry);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Adds two values.
*
* @func
* @memberOf R
* @since v0.1.0
* @category Math
* @sig Number -> Number -> Number
* @param {Number} a
* @param {Number} b
* @return {Number}
* @see R.subtract
* @example
*
* R.add(2, 3); //=> 5
* R.add(7)(10); //=> 17
*/
exports.default = (0, _curry3.default)(function add(a, b) {
return Number(a) + Number(b);
}); Not really sure where we want to take it from here. |
Oh I totally forgot about the default thing. Well, its only needed for backwards compatibility so as long there is need for that you should use the babel-plugin-add-module-exports in addition to
{
"plugins": [
"add-module-exports",
"transform-es2015-modules-commonjs"
]
}
Sorry for the extra work you had to do. |
The unnecessary cruft babel adds to the generated commonjs modules affects only browserify\webpack users --> There are 2 use cases I'm familiar with:
** EDIT ** |
Super excited about the progress being made on this issue. The bundle size reduction with webpack is something I would use immediately. One thing to consider after releasing the support for individual function import might be a babel plugin for auto modularization. Lodash has a useful one: This would allows users to import ramda and use it normally, but transform their code into the 'modular' version. |
@mjrussell I mentioned before the babel-plugin-ramda. My PR with babel 6 support was merged few hours ago :) |
@borisirota oops sorry totally missed it! 👏 |
Has there been any progress on this? Would love to get modular ES6 builds with webpack 2.0 getting tree-shaking. I'll definitely look into the babel plugin, but having that built-in would be even better. Any place I can help out? |
@scott-christopher: Any thoughts on where to go from here? |
I have very little time available to look into this further at the moment, though I wonder whether we might be better off keeping all the existing source files as they are and instead generate the ES6 module files on the fly before deploying to NPM. Then we could just add The following bash script should get close to that (I'm sure that someone more knowledgeable in the magical world of shell scripting could improve upon this) if run before the deploy. #!/usr/bin/env bash
set -e
REL_SCRIPT_DIR=$(dirname "$0")
ABS_SCRIPT_DIR=$(cd "$REL_SCRIPT_DIR"; pwd -P)
PROJECT_DIR=$(dirname "$ABS_SCRIPT_DIR")
mkdir -p "$PROJECT_DIR/es/internal"
for f in $PROJECT_DIR/src/*.js $PROJECT_DIR/src/internal/*.js; do
sed -e 's/var \(.*\) = require(\(.*\));/import \1 from \2;/g' \
-e 's/module.exports =/export default/' \
"$f" > "$PROJECT_DIR/es/${f#${PROJECT_DIR}/src/}"
done
find "$PROJECT_DIR/src" -type f -depth 1 | sed -e "s|.*/\(.*\)\.js|export { default as \1 } from './\1';|g" > "$PROJECT_DIR/es/index.js" If anyone wants to explore this further, I'll gladly help where I can. |
I think if we want to embrace more of ES6 with the current codebase, we should perhaps seriously consider tagging |
The However, this currently is no |
There is a line in the script above that takes care of that: find "$PROJECT_DIR/src" -type f -depth 1 | sed -e "s|.*/\(.*\)\.js|export { default as \1 } from './\1';|g" > "$PROJECT_DIR/es/index.js" I had a quick attempt at getting tree shaking to occur with a simple example, though couldn't get it to work using Rollup while importing the index file. To test locally, I generated the ES modules in a local copy of Ramda using the script above within the The following were some various results of running Importing from import { add } from 'ramda';
export default add(10); Converted to the following without inlining the dependencies: 'use strict';
var ramda = require('ramda');
var add10 = ramda.add(10);
module.exports = add10; Importing the index file via a relative path: import { add } from './node_modules/ramda/es/index';
export default add(10); Converted to ... the entire ramda source with something similar to I also tried different formats of the index file to see whether that would help like having separate import and export statements rather than the So in summary, I'm happy to help this along, though I don't have much experience with tree shaking using either Rollup or Webpack 2, nor do I have much time available to me at the moment to investigate much further so I'd be happy if someone else wanted to pick this up. ** UPDATE ** import resolve from 'rollup-plugin-node-resolve';
export default {
plugins: [resolve({ jsnext: true })]
}; |
@borisirota I love you! babel-plugin-ramda is just what I needed! |
Any news on this? I guess it wouldn't be difficult to restructure Ramda to allow for this, but I don't have time myself. |
From what I see in the code, what could be done is:
Sure, the publisher will end up with a pretty dirty git state, but:
Then Let me know if you like this approach and in that case, if building each file in |
I think it's a good idea, and I have no problem removing |
If the code is restructured, would it be worthwhile bundling the tests and code together? |
I didn't think we were discussing removing Your suggestion has merit of its own as well as its own controversies, but it would be a separate change, and a very separate discussion. |
Apologies for spamming here too, but there seemed to be a couple of threads discussing related issues. I made a quick script hack that converts Ramda to support Rollup and UglifyJS2 Note that compared to previous attempts at similar hacks ( ping @scott-christopher ), the In my particular case, looking at the bundle after uglifying it, there seems to be a lot of code related to transducers even though I'm not making any use of those. It might make sense try to reduce the impact of transducer support in Ramda (the code is quite verbose) or change it so that it could be dead code eliminated when not used. Addition: The hack is now also available from NPM. See here. |
Thank you very much. I look forward to investigating this. Hopefully this evening. |
+1 |
With #2254 now merged, can we close this? |
Sorry if this is not the right place, but I am confused about what the ES folder. I use Webpack 3 with just the Uglify plugin, and I failed to reduce my bundle with the ES exports: Thank you. |
cc @Andarist |
Unfortunately webpack is not really that great when it comes to its tree-shaking. I hope it will be improved in the future. For some reason why I think so you might look into this. When using webpack 2+ or rollup When it comes to "cherry-picked" modules (like your For more information you should read this thread and its comments. |
@Andarist Is there any benefit to |
In webpack? Probably not that much in terms of tree shaking, however In example webpack's Whenever possible you should use |
my proposal
The text was updated successfully, but these errors were encountered: