-
-
Notifications
You must be signed in to change notification settings - Fork 626
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
Update extractTextPlugin transformation #390
Update extractTextPlugin transformation #390
Conversation
use: ExtractTextPlugin.extract('style-loader', 'css-loader') | ||
use: ExtractTextPlugin.extract({ | ||
use: 'css-loader', | ||
fallback: ['style-loader', { loader: 'test-object-loader' }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to fully demonstrate that string, object, and array loader configurations all work via this test case.
// Add new loader | ||
loaderPath && Object.assign(loaderPath, { | ||
value: currentFallbackLoader ? | ||
j.conditionalExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MiniCssExtractPlugin
does not support fallback
and disabled
options. Instead, users should manually swap out MiniCssExtractPlugin.loader
with the loader that was normally used as a fallback
, which is what we're doing with this ternary. More information can be found here.
I found some problems. I have this configuration (that was not created by me) and i think it is a good "point out of the curve", since people can still have things like this: https://gist.github.com/PlayMa256/0a51b41e1b0eba910869764f378bf932 This was the generated config: https://gist.github.com/PlayMa256/587b2d3890c9c96e3f3dbe567c8ecfce As you can see, few problems occurred:
|
Good catch and feedback. On it now. |
Well, the null problems seems to be gone. In the example i sent you (which is kind absurd i Could you create a test for multiple loaders in a rule?
A scenario similar to this? That could show problems if it fails. |
@playma256 @ematipico I updated the logic so options are only passed if they're defined and After digging into multiple-instance support a bit more, it looks like we need to only support migrating configurations with a single instance of This is the best we can do for now and we can put a caveat in the documentation until webpack-contrib/mini-css-extract-plugin#45 is resolved. |
Oh, got it! I did not know about this problem, i just found this tricky |
@ematipico this is a nice PR for you to test & to get more knowledge of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you abstract this into JScodeshift utilities? A loot of specific code for the nodes, would be nice to use things like j(p.identifier)
etc
Thanks, I moved most functionality to |
* | ||
* @param {Object} j - jscodeshift top-level import | ||
* @param {Node} ast - jscodeshift ast to transform | ||
* @returns {Node} ast - jscodeshift ast | ||
*/ | ||
|
||
module.exports = function(j, ast) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
named functions
lib/utils/ast-utils.js
Outdated
* @param {any} j — jscodeshift API | ||
* @param {Node} node - Node to start search from | ||
* @param {String} pluginName - name of the plugin to remove | ||
* @param {Node | Void} - path to the root webpack configuration object if plugin is found |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing return
* Calls an function with a path wrapped in an array, using path.elements if available | ||
* | ||
* @param {NodePath} path - path to wrap in array | ||
* @param {Function} action - called with array path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing return
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added @returns {Void}
.
) | ||
); | ||
p.value.arguments = [newArgs]; | ||
const devLoaders = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you abstract all this into more functions that can be reused, like find value "filename" for a given prop
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure I follow; we already abstracted functionality into simple, single-purpose functions like getPluginOptionValue
and getLoaderOptionValue
. If we start getting even more abstract than this, we risk targeting nodes that aren't actually the nodes we care about. For example, someone could define filename
completely outside of the webpack configuration object for unrelated purposes, so we need to be very careful which filename
identifier we actually target.
The functions I already pulled out (createPluginByName
, removePluginByName
, getLoaderOptionValue
, getPluginOptionValue
, and removeRequire
) are reusable and safe.
@bitpshr Thanks for your update. I labeled the Pull Request so reviewers will review it again. @ev1stensberg Please review the new changes. |
let pluginExists; | ||
let requireExists; | ||
|
||
const filename = getPluginOptionValue(j, ast, "ExtractTextPlugin", "filename"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you extract these into more functions that could be reused?
* @param {any} j — jscodeshift API | ||
* @param {Node} node - Node to start search from | ||
* @param {String} pluginName - ex. `webpack.LoaderOptionsPlugin` | ||
* @param {Object} options - plugin options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returns?
* @param {any} j — jscodeshift API | ||
* @param {Node} node - Node to start search from | ||
* @param {String} constName - Name of require | ||
* @param {String} packagePath - path of required package |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
returns
@ev1stensberg thanks for the reviews. Everything has been addressed except for the following comment:
What type of functions were you imagining? I already abstracted almost all logic into |
Thanks @ematipico. Could you please see my comment above and take another look when you have a chance @ev1stensberg? Thanks in advance! |
pluginExists && createPluginByName(j, ast, "MiniCssExtractPlugin", loaderOptions); | ||
|
||
// Remove old loader | ||
ast.find(j.Identifier, { name: "ExtractTextPlugin" }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be abstracted into an util, maybe you can make it general so that we can reuse it for later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pulled most of this logic out into a new findLoaderFunction
utility function. It allows us to target loaders that use call expressions, e.g. use: SomeIdentifier(...)
. I could not pull everything out into a removeLoaderFunction
because we need information during the traversal. This is the best we can do.
}); | ||
|
||
// Add new loader | ||
const loader = currentFallbackLoader ? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be another util, addLoader
|
||
// Add new loader | ||
const loader = currentFallbackLoader ? | ||
j.conditionalExpression( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be too specific, is there another way of adding a loader?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created an addConditionalLoader
utility function per your comment above. I think it'll be useful in the long run, as it makes it easy to add loaders based on NODE_ENV
.
Thanks @ev1stensberg. This should be as generic as possible now. Let me know your thoughts. |
Thank you for your pull request! The most important CI builds succeeded, we’ll review the pull request soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, we can always change it later
Thanks @ev1stensberg. Rebased. |
What kind of change does this PR introduce?
Feature
Did you add tests for your changes?
Yes
If relevant, did you update the documentation?
N/A
Summary
After some discussion the decision was made to update our migration transformations to actively support migrating only from the previous version to the current version, which currently means
v3 - v4
. Migrating older versions such asv1
orv2
will no longer be supported. This PR begins this work by updating theextractTextPlugin
transformation. Resolves #373.Note:
v3
configurations that contain multipleExtractTextPlugin
instances are not yet supported due to a limitation withMiniCssExtractPlugin
.Does this PR introduce a breaking change?
Yes. This PR changes
ExtractTextPlugin
migration behavior and produces av4
-specific configuration.Other information
This PR only includes updates to the
extractTextPlugin
transformation. The following issues have been opened for the remaining transformations: