-
Notifications
You must be signed in to change notification settings - Fork 94
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
API for version 1.0 #125
Comments
FYI: This is pretty much the result of the #34 discussion 😉 |
I think this is a good change. It allows the extract text plugin to be used with any css preprocessor, because in a post hook, you can search the config for all loaders containing the style loader and use its mime type for the extract text plugin |
Plus it keeps simple blocks as simple as they used to be because of merge |
@andywer I love the idea of making what's going on more explicit. What I'm not 100% convinced though is why do we need a util parameter? If we are truly functional, wouldn't make sense to import those helpers instead? |
With the parameter you dont have to update tge blocks if the core changes |
@eXon Hmm. I don't think it contradicts the functional approach. My main argument for the helpers object is just preventing the blocks from all depending on the same util package. It should just cover the very most frequently used functions, so it's still very easy to write a block as a function without additional dependencies :) |
Like Andy, I don't think that this has a bearing on whether or not the api is functional, but after thinking about it some... what it does do is make a dependency implicit that should probably be explicit. There are problems around versioning something like this. Specifically, if a new util function is added and a 3rd party block uses it, then that block now has an implicit dependency upon that specific version of webpack-blocks. It would have to specify a peerDependency to make that explicit, but that is not forced and may be missed. Of course any other change to the util functions carry the same problem--parameter changing/renaming/etc. In other words, there is still a dependency, it's just implicit and not required. It's the opposite of "pit of success" There is also the unit testing issue discussed here. The fact that these functions are injected led to testing them in an incomplete way. To test them in a complete way requires more work than it should. I would propose a core package (maybe just called All blocks then would depend (probably still via While passing utility functions in is "easier", I think that making those dependencies explicit is "simpler". |
I understand your implicity concern, but in terms of block development convenience I would still favor the passed-down utility methods. A block should be really simple to write and ideally be zero-dependency stuff. If you need to do a complicated config manipulation you can import some external functions to help you at any time. But I really think you shouldn't have to for the usual cases. Maybe it's a lot of personal flavor, but I always adored the cleanness of flummox and later redux: There was not a single import necessary; a completely transparent API. This embraces writing pure functions a lot and I would like to go a similar way here.
There is always a subtle dependency between the block that exports a function implementing some interface and the We can make that dependency explicit by adding But I don't see an advantage when making the blocks import the utility functions. The dependency is basically the same as when receiving it via a parameter, the way of getting it is just different. And I fear that other developers might accidentally add them as |
Sorry for the wall of text 🙈😉 |
Im on Andy's side here, blocks shouldn't need depenencies |
My concern was around versioning. If you have 2 versions of webpack-blocks in the wild, one of which has the A bug report on the 3rd party block may lead them to adding a peerDependency on the specific version of webpack-blocks they depend on. This would be a good thing and may save others from stubbing their toe in the same way. This gets even worse when considering the impact of updating
Sorry, but inverting dependencies does not make the dependencies go away. They're still there. Blocks still depend on webpack-merge, they just don't know it or have the ability to specify which version they're going to get. I'm probably pedantic here. No worlds will end as a result of the bugs/frustration this could potentially cause. By the way, I think I was mistaken in my last post. If we were to force end users to require the utility functions, they should be declaring |
Ok, yeah that makes sense |
One other suggestion: Put all the utils in their own package, |
My solution was about versioning ^^ Updating the webpack-merge dependency works the same. It requires at least a minor version bump. As long as everyone sticks to semantic versioning it will be fine. If not we are doomed anyway, I fear. Tell me if I am making things too easy here... 😉
Right, if that solution then definitely as a separate package :) |
Sorry, I must be missing something. From what I can tell, semver/versioning have no impact on what you have proposed. You can bump 5 major versions and a 3rd party block that does not have a dependency or a peerDependency on In order for semver/versioning to matter, packages must depend directly (or transitively) on the packages being versioned. Your proposal makes that unnecessary, so people won't do it. My proposal was to make it necessary by forcing them to actually depend on the package that they depend on explicitly. Am I missing something? |
No, I meant in combination with peerDependencies 😉 But yeah, you have a point: peerDependencies rather feel like recommandations. They cannot enforce anything really... I am still not liking the idea that pretty much every block will have to add this utils dependency. My gut says "pass them as parameter, limit them to the absolute minimum functionality and only change them on major version bumps when breaking changes will make updating the blocks necessary anyway". But you also have a point in making that dependency explicit. I guess I am too close to the issue right now, need to get a little distance first. |
At the end of the day, I don't think it is a big deal either way. It's unlikely to really cost anyone that much time and very unlikely to cause production issues. I'd be totally happy with it being however you like. |
Ok, let's do it like this: We are still some PRs away from the release and there is a working PR including the utility functions now (#128). Let's use it as it is for the moment and we still have time left to open another PR changing it if we want. Agree? :) |
Works for me! By the way, webpack-merge 4.0 was released which includes a patch that may fix the original issue with extract text. Whether or not it fully fixes it actually depends on whether or not the extract text plugin loader includes the fallback loader in its loader chain. Any way, it's a better behavior for us, so I'd suggest upgrading as part of 2.0 |
Thanks for the link. It's a useful change, but I don't think it will solve the extract-text issue. It will improve the order of the loaders when merging definitions sharing the same loaders, but in the extract-text case we need to remove the loaders and add a new one... |
I thought so too, but it turns out that |
Ahh, but that is interesting. |
After thinking about this some more, i have to agree with @aaronjensen here. But in the end the difference is minimal |
Nice job guys! My only issue with it is that most of the times you wouldn't need the context, so it would be ideal if it was optional, and the first argument would be a big object containing module.exports = function resolveSrc() {
return ({ merge }) => merge({
resolve: {
modules: ['node_modules', 'src'],
},
})
} What do you guys think? |
Hey @marcofugaro. This is indeed a good catch. @aaronjensen Do you guys already use the new API / the release branch? |
I'd say globs are user-friendlier and easier on the eyes for matching file types. Like I first thought about using minimatch, but glob-to-regexp seems to be a better choice for turning globs into regexps. (I tried both) |
I have a first working prototype. It's work in progress, but the diff of the @webpack-blocks/assets README provides a pretty neat foretaste I think. Feedback is as always highly appreciated, though 😉 |
I like the API! ;-) |
(In case you didn't see it: The PR is open - #163 😉) |
@andywer What is the support for Webpack 3 going to look like? Or is that being considered in this release? |
Webpack 3 comes with no breaking API changes that would concern webpack-blocks, so I am just adding it to #134. That reminds me... Right now |
I had a thought the other day why are helper functions passed as a separate argument? They should be a part of the context, aren't they? |
@vlad-zhukov Fair enough. The original line of thought goes like this: The context is a thing where data can be stored that should be shared by multiple blocks or between hooks. Since the helper functions are helper functions and not shared data, they are passed separately. But of course you can argue that it's just a question of re-defining the purpose of the context 😉 And yeah, we still need to settle on the future of those helper functions... 🙃 |
I see but |
But it doesn't always seem intuitive where to draw the line, so you are not wrong, though 😉 The main question right now is still:
There seems to be a small majority in favor of the 2nd option. |
ImportantSooo. This is probably the longest running discussion of the project and there was a lot of valuable feedback, yet no complete consensus yet. My suggestion: But for now I'd like to take the fastest route leading to a working 1.0, since 0.4 should be deprecated as soon as possible. |
Do it! |
For mid-term consideration: I slowly feel like changing my mind towards what @vlad-zhukov wrote earlier: Might make sense to put the utils (2nd parameter: Main benefit: There will always be blocks that want the utils, but not the context, and blocks that want the context, but no utils. In the former case you currently end up with a |
@andywer I think that the old API should be completely removed in the 2.0 release. |
@andywer I think it's better to put helper functions into block instance's options, i.e.: function css () {
- return ({ context, util }) => util.addLoader({
+ return ({ context, addLoader }) => addLoader({
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ],
...context.match
})
} |
@dmitmel Maybe, but this is the wrong issue for that 😉 |
@andywer Well, this can be an API for v2.0, but it's better to introduce one breaking change than two. |
v1.0 has been released. |
@andywer Hooray! |
After thinking a lot about it quite a long time, encountering several edge-cases with the current API and a long discussion with @aaronjensen I want to present the draft for a slight API change.
It is a breaking change, but migration is straight-forward. The version bump 0.x => 1.0/2.0 seems to be an obvious choice for introducing such a change.
Old (current) API
Block written for old (current) API
The main issues here are:
(Pre and post hooks work as before, just that the post hooks will adapt the new API as well. Pre hooks don't actually emit configuration, so they don't need to be changed.)
New API
Block written for new API
With the new API the modification of the configuration object is not just more explicit, but the main feature is that the block now has full control on how to merge new content into the configuration, like if some item will be prepended or appended to an array.
List of helper functions (Might still be subject to change)
merge(configSnippet: object)
addLoader(loaderDefinition: object)
addPlugin(pluginInstance: Plugin)
@eXon @jvanbruegge @sapegin
The text was updated successfully, but these errors were encountered: