-
-
Notifications
You must be signed in to change notification settings - Fork 927
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 Mithril modular #651
Comments
The cynic in me believes the ~1000 bytes you'd save would be others' loss via boilerplate. …But I have an interest in making Mithril more modular for the sake of code transparency and maintenance, so I'm intrigued by the idea :) Do you have any ideas for a process? I'd be up for helping on a fork… |
Well, the routing and request parts (line 676 onward) are ~500 (unminified) lines out of Mithril's ~1200, so I wouldn't say the savings are negligible. The process is fairly straightforward, figure out function dependencies, split them into sensible (CommonJS) modules ( The build output will be functionally the same as the current script (no boilerplate), while people could also use I've broken up several large scripts like this, it's not too painful and should be almost painless considering Mithril.js is small and modular in nature. I'll try to have something up in a couple days. |
👍 |
I'd recommend looking at Duo, imo the most comfy build system & package manager right now. You don't even have to publish to 3rd party sites, as it uses github repos as its registry. |
I'd recommend leaving it alone until ES6 modules are in all the browsers that matter. |
@darsain I'm inclined against Duo, since it piggy-backs on the established and de-facto-standard CommonJS/Node end-use API but violates the package identification strategy embraced by every major standard, which is to defer resolution to external methods (ie package.json). Duo distinguishes itself on the ability to resolve Github @lawrence-dol providing modular builds does not mandate that Mithril application developers (or Mithril application users) be able to use any particular module import / registry / resolution method or have any particular stack, it just makes it possible to use Mithril modularly. Mithril is already UMD-compliant, in that it will work with Node, Browserify, RequireJS, SystemJS, or as a plain global script injection. We should absolutely maintain that. For those of us using vanilla JS included by script, this would mean either simply including |
+1 for modularity! |
+1 for modularity! I love webpack. It can bundle everything. You can write source in CommonJS format, then bundle it unto an universal library build (which supports global, AMD, commonJS modules). |
Duo has
Mithril perhaps doesn't need CSS packaging, but every website, and possibly modules/components that consume mithril definitely would. It seems silly to dismiss a tool because it has a feature your particular case doesn't need. And duo also supports packaging and consumption of almost any other files, such as json, fonts, html templates, ... very useful.
Making mithril modular would not take this away. You'd still have a final monolithic file for people that use raw scripts, which would be just a composition of mithril modules: module.exports = exports = require('mithril/m');
exports.route = require('mithril/route');
exports.component = require('mithril/component');
// ... and build with Making mithril modular would also mean better and more maintainable source code structure. You'd be able to split big internal functions into files like var build = require('/lib/build'); You'd also be able to remove inlined stuff which should be left for dependencies, such as your own promise, ajax, routing, data binding, etc. solutions. You could split them to modules, and add them to the monolithic file, leaving people who want to use mithril modularily with an option to pick their preferred solutions. From all the front-end package managers I've tried duo was the best to use. The only issue is that it's not backed by any large company, and that hinders its adoption. Anyway, there's my 2¢. |
I'm using the full Mithril feature set in production with just the plain vanilla JS script and grunt reduce [1]. I quite like it this way. I don't want to see it get more complicated than it needs to be. My 2 cents. |
@Jafula to re-iterate what @darsain was saying above, the proposal would maintain total backward compatibility. jQuery and Lodash are fully modular builds – it doesn't impact basic plug-and-play at all. Mithril currently uses Grunt as a build system, but that's completely orthogonal to how you want to use it. |
I might add to what @darsain said, that if Mithril has no dependencies now (and maybe already has, but «melded»), it is not a eternal state of things. Every non-utility project one day acquire some deps. And when this day comes some builder/bundler would be required. But even without deps Mithril will gain benefits of modularity. |
kb The three convenience services built into Mithril that some developers choose to circumvent with their own solutions are Importing an xhr solution would require importing promises as well. I'd venture that the combination of these imports would occupy more real estate than the current implementation. m.request occupies about ~10% of the code. xhr and routing both require access to the autoredraw system which would have to be re-written Current 3rd party routing options are just wrappers around m.route. m.route occupies about ~10% of the code. @lhorie has demonstrated that 3rd party promises are an option now. That's nearly a 30% reduction in code base. It's not clear how much of that savings would be lost to making Mithril plugin friendly. But the benefits of opening the code up for a plugin ecosystem might be well worth the extra bytes. BTW |
#665 I've made a PR. The cost is 5kb unminified, 2kb minified. Building just the virtual DOM functionality is ~34kb. All the tests pass for the bundled script, but I haven't made any extra tests or tried testing any one module. The router and http modules import the DOM module since they cause redraws but changes can be fairly easily made to opt out if the functionality isn't detected.
|
I believe it would be great if we could separate the router from mithril.js - and call it mithril-router.js - as I do not think everyone would want to use it. The router is nice, but if it's not being used, then it could be a single node module that is pluggable. |
For a build tool needed to put Mithril modules together into one script, instead of Grunt, Gulp, Duo, Webpack, or something similar, I wonder if just plain npm might suffice? See Keith Cirkel's approach: "Last month I noted my opinions on why we should stop using Grunt, Gulp et al. I suggested we should start using npm instead. npm's scripts directive can do everything that these build tools can, more succinctly, more elegantly, with less package dependencies and less maintainence overhead. ... npm is a fantastic tool that offers much more than meets the eye. ..." I feel just using npm with some simple scripts might be more in keeping with Mithril's elegant less-layers-to-go-wrong design. |
I remember this request has been made by some one else before. I just don't want to wait to be resolved, so I build some stuff myself just for fun:). I call it mReact, only using the rendering part of Mithril, and code is modularized. Check it out if you are interested. |
Would very much like if m.sync, m.request and others were moved into separate packages so that mithril would focus on the view aspect only. I personally use es6-promise polyfil for promises and have been using superagent for async http requests... I don't mind using m.request at all but it would be neat if I could choose on my own. But overall I really like Mithril alot. But I'm afraid that it could loose focus. Perhaps there could be a bundled version called Mithril which includes mithril-ui/dom/vdom/whatever, mithril-request, mothril-router etc. Just an idea. And as said - the build process for the release of Mithril would remove all the boiler plate. Would make it possible for others to just use certain parts. Don't know if this is possible of even a good idea. |
@jakobdamjensen WRT m.sync/m.deferred, see #800. It's come up quite a few times on Gitter. Also, m.request is otherwise largely independent of the rest of the library. Most of the small utilities are standalone. The rendering is so highly coupled, forget about modularizing it. And half of m.route and m.mount overlap with the renderer. The incredibly tight coupling in about 50% of the framework is a known problem. And it's not an easy thing to fix at the moment. |
I want the mithril.js's source code like Vuejs's structure. that's comfortable and more readable |
Why not make another repo/branch/whatever and keep the monolithic version in master and npm? // first time I used it
import _ from 'lodash'
//later, when I'm more comfortable with the lib
import sortBy from 'lodash/collection/sortBy' What's wrong about that? By the way, it was kinda hard to know how to import only the function I was interested in. I think mithril should keep its concept of simplicity and in this case, unity. |
@veggiemonk nobody suggested lodash was doing things wrong. And, as your example shows, it's entirely possible to do this without separate branches, using the same package. There's basically nothing to worry about with modularising the source code — novice users shouldn't even notice anything's changed :) |
Hey @barneycarroll ,
Exactly the goal I was trying to ouline. Thanks for that! Novice users should be able to load the whole lib. If it is just like the example of lodash. I think everybody will be pleased. |
Ideas that spawned on #665:
Currently, the consensus is leaning towards the third, but I thought I would put something here. /cc @barneycarroll @pygy @lawrence-dol @veggiemonk This summary accurate? |
Another Rollup pro / concatenation con is the fact that it documents interdependencies.
|
I am trying hard not to have much of an opinion, because as @barneycarroll has pointed out I am not an active contributor yet (in part because I work too much already, and it part because (gasp) I've only just started using Git recently). So I'll just repeat my post with my reasoning from #665 for the sake of this thread and bow out in respect to those who are actively contributing. (I added a little.) My vote is far, far and away for a simple concatenation of plain JS and no magical tool chain. I do want to preserve my ability to contribute to Mithril, and I doggedly refuse to use the complex and unnecessary 10-million-dependency tool chains that others seem to love so much. Equally as much, if Mithril dies, goes south or off and away to becoming a "jack of all trades, master of none" framework, I can simply go on with whatever was the last version that made sense. The tight focus and tiny footprint is the primary reason I chose to build on top of Mithril; heck it does a thousand times more for me than I've tried Sencha, Sencha Touch and KendoUI; they all started off well and rapidly got to the point where they sucked harder than a black hole at the event horizon. Not to mention the 5,000 files they added to every project. No thanks, not any more. Not again. My $1.99 (inflation). |
I don't think rollup will add too much since it flattens out all dependencies. Also I think it's prematuraty is not a big problem since we can run the tests against the build and we should be fine. In the first place I would create 2 bundles one for mithril beeing globally available and one common-js version. In the next steps we can create custom builds for the different parts of mithril. Until then rollup might be in a good shape. It will certainly not die, if google is already using it. For me it would also be ok to use browserify. The overhead is relavant compared to the size of mithril but not to the size of a decent sized project. For the people who care about the last bit we can also provide a custom build where all require stuff is flattend out. I think there is an option in browserify for this. I understand @lawrence-dol concerns: If we have the modularized mithril in place, it's easy to add more and more features to it. But in the current state, it's hard for people to contribute I think (I did'n make any PR so far). It's a matter of discipline not to overload the framework with stuff that might be already solved anywhere else. An for the books: First thing we want to do with modularisation is to strip things out of mithril :) |
@IMPinball Thanks for summing that up. TL;DRBuild steps add complexity. From my experience, build steps are a pain. Unless you're willing to include your own like lodash custom builds which I've never used by the way because there is a I use mithril for its simplicity and great documentation. So adding a custom build step sounds like a terrible idea, unless someone make it great (you never know). This is a table taken from @nordfjord presentation about mithril ( link to repo )
Is that really too much of an api that we need to strip it down? I think that it's @lhorie decision and whatever is decided I will be ok with it. |
The biggest hindrance to modularizing is that Mithril has so much coupling Or to use an analogy, Mithril uses the stove's wiring to also power the TV Do it all in one pass, though, and you've displaced the inhabitants. You Ignore the problem, and seemingly unrelated things will stop working when a You want to make each room independent of the others? You first have to Or in other words, this will take a while to fix. I'm probably going to On Thu, Nov 26, 2015, 13:43 Julien Bisconti notifications@github.com
|
While decoupling Mithril may be nice, it is not a prerequisite to use rollup, since it manages circular deps just fine. |
Still, would you prefer arbitrary modules, but with all the coupling and On Thu, Nov 26, 2015, 21:26 Pierre-Yves Gérardy notifications@github.com
|
Brace yourself for what may sound like heresy: shared references are exported as properties from a discrete internal 'model' module. The module is only imported internally and is not exposed in the public export. It would be possible for a consumer (using CommonJS) to import that module from the file system and mess with these properties if they really wanted to, but they'd have to go out of their way to do so. Even if this leaves a bad taste in people's mouths, it might at least help to isolate and rationalise the shared internal model and map dependencies — it could be a valuable interim to refactoring the 'one big closure' nature of Mithril. You may be thinking it's not as easy as all that because some of these variables need initialisation and persistent reference, but we can get around that with closured getter / setters, ie custom m.props. |
That's also where I was coming to when I said it would make it easier to navigate the source. In the process, you'll document internal dependencies. re. initialization/persistent references, I haven't been in Mithril's source for a while, but unless you must mutate said references from another module, ES6 modules support it out of the box |
Another great thing about Rollup is that rolled up test suite could import and test otherwise private and previously untestable parts of Mithril. Edit: I mean, without any extra boiler plate in the final package. |
@IMPinball Now I understand why it is important to make mithril modular. I didn't really understood it until I tried to modify mithril's code myself. Sorry for my intervention, I was reasoning with only ideas and i think now it is important to make mithril modular in order to allow further improvement and extension such as es6 modules. |
This is in the roadmap, so I'm going to close this issue for now |
I love the framework and have integrated it into my application. However, I'm using Angular (and am stuck with it) and don't need Mithril's router and http libraries. Would it make sense to make the code base use modules so that I can import just the parts I need?
The text was updated successfully, but these errors were encountered: