Skip to content

Update extractTextPlugin transformation #390

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

Merged
merged 6 commits into from
Apr 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,23 +1,71 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`extractTextPlugin transforms correctly 1`] = `
"let ExtractTextPlugin = require('extract-text-webpack-plugin');
let HTMLWebpackPlugin = require('html-webpack-plugin');
exports[`extractTextPlugin transforms correctly using "extractTextPlugin-0" data 1`] = `
"const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.export = {
module: {
rules: [
{
test: /\\\\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
use: (process.env.NODE_ENV === 'production' ? [MiniCssExtractPlugin.loader, 'css-loader'] : ['style-loader', { loader: 'test-object-loader' }, 'css-loader'])
}
]
},
plugins: [
new ExtractTextPlugin(\\"styles.css\\"),
new Foo(),
new MiniCssExtractPlugin({
filename: 'foo.css'
})
]
}
"
`;

exports[`extractTextPlugin transforms correctly using "extractTextPlugin-1" data 1`] = `
"const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.export = {
module: {
rules: [
{
test: /\\\\.css$/,
use: ['css-hot-loader'].concat((process.env.NODE_ENV === 'production' ? [MiniCssExtractPlugin.loader, 'css-loader'] : ['style-loader', 'css-loader']))
}
]
},
plugins: [
new Foo(),
new MiniCssExtractPlugin({
filename: 'foo.css'
})
]
}
"
`;

exports[`extractTextPlugin transforms correctly using "extractTextPlugin-2" data 1`] = `
"const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.export = {
module: {
rules: [
{
test: /\\\\.css$/,
use: [
'foo-loader',
(process.env.NODE_ENV === 'production' ? [MiniCssExtractPlugin.loader, 'css-loader'] : ['style-loader', 'css-loader']),
'bar-loader'
]
}
]
},
plugins: [
new Foo(),
new MiniCssExtractPlugin({
filename: 'foo.css',
publicPath: 'public'
})
]
}
"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.export = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
use: 'css-loader',
fallback: ['style-loader', { loader: 'test-object-loader' }]
})
}
]
},
plugins: [
new Foo(),
new ExtractTextPlugin({
id: 'foo',
filename: 'foo.css',
allChunks: true,
disable: false,
ignoreOrder: true
})
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.export = {
module: {
rules: [
{
test: /\.css$/,
use: ['css-hot-loader'].concat(ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'style-loader'
}))
}
]
},
plugins: [
new Foo(),
new ExtractTextPlugin({
id: 'foo',
filename: 'foo.css',
allChunks: true,
disable: false,
ignoreOrder: true
})
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.export = {
module: {
rules: [
{
test: /\.css$/,
use: [
'foo-loader',
ExtractTextPlugin.extract({
use: 'css-loader',
fallback: 'style-loader',
publicPath: 'public'
}),
'bar-loader'
]
}
]
},
plugins: [
new Foo(),
new ExtractTextPlugin({
id: 'foo',
filename: 'foo.css',
allChunks: true,
disable: false,
ignoreOrder: true
})
]
}

This file was deleted.

133 changes: 86 additions & 47 deletions lib/migrate/extractTextPlugin/extractTextPlugin.js
Original file line number Diff line number Diff line change
@@ -1,58 +1,97 @@
const utils = require("../../utils/ast-utils");
const {
addConditionalLoader,
addRequire,
createPluginByName,
findLoaderFunction,
getLoaderOptionValue,
getPluginOptionValue,
pathToArray,
removePluginByName,
removeRequire
} = require("../../utils/ast-utils");

/**
*
* Check whether `node` is the invocation of the plugin denoted by `pluginName`
*
* @param {Object} j - jscodeshift top-level import
* @param {Node} node - ast node to check
* @param {String} pluginName - name of the plugin
* @returns {Boolean} isPluginInvocation - whether `node` is the invocation of the plugin denoted by `pluginName`
*/

function findInvocation(j, node, pluginName) {
let found = false;
found =
j(node)
.find(j.MemberExpression)
.filter(p => p.get("object").value.name === pluginName)
.size() > 0;
return found;
}

/**
*
* Transform for ExtractTextPlugin arguments. Consolidates arguments into single options object.
* Transform for ExtractTextPlugin. Replaces it with MiniCssExtractPlugin and translates
* configuration where possible.
*
* @param {Object} j - jscodeshift top-level import
* @param {Node} ast - jscodeshift ast to transform
* @returns {Node} ast - jscodeshift ast
*/
module.exports = function transformExtractTextPlugin(j, ast) {
const devLoaders = [];
const prodLoaders = [];

let elements;
let loaderIndex;
let loaderPath;
let newElements;
let pluginExists;
let requireExists;

const filename = getPluginOptionValue(j, ast, "ExtractTextPlugin", "filename");
Copy link
Member

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?

const publicPath = getLoaderOptionValue(j, ast, "ExtractTextPlugin", "publicPath");
const currentFallbackLoader = getLoaderOptionValue(j, ast, "ExtractTextPlugin", "fallback");
const currentLoader = getLoaderOptionValue(j, ast, "ExtractTextPlugin", "use");

module.exports = function(j, ast) {
const changeArguments = function(p) {
const args = p.value.arguments;

const literalArgs = args.filter(p => utils.isType(p, "Literal"));
if (literalArgs && literalArgs.length > 1) {
const newArgs = j.objectExpression(
literalArgs.map((p, index) =>
utils.createProperty(j, index === 0 ? "fallback" : "use", p.value)
)
);
p.value.arguments = [newArgs];
const loaderOptions = filename || publicPath ? {} : null;
filename && Object.assign(loaderOptions, { filename });
publicPath && Object.assign(loaderOptions, { publicPath: publicPath.value });

// Remove require for old plugin
requireExists = removeRequire(j, ast, "ExtractTextPlugin");

// Add require for new plugin
requireExists && addRequire(j, ast, "MiniCssExtractPlugin", "mini-css-extract-plugin");

// Remove old plugin
pluginExists = removePluginByName(j, ast, "ExtractTextPlugin");

// Add new plugin
pluginExists && createPluginByName(j, ast, "MiniCssExtractPlugin", loaderOptions);

// Remove old loader
const loaderCallPath = findLoaderFunction(j, ast, "ExtractTextPlugin");
if (loaderCallPath) {
loaderPath = loaderCallPath.parent.value;
loaderPath.elements && (elements = [...loaderPath.elements]);
j(loaderCallPath).remove();
}

// Build loader arrays
currentLoader && pathToArray(currentLoader, switchedLoader => {
const loader = j.memberExpression(j.identifier("MiniCssExtractPlugin"), j.identifier("loader"), false);
prodLoaders.push(loader, ...switchedLoader);
currentFallbackLoader && pathToArray(currentFallbackLoader, switchedFallbackLoader => {
devLoaders.push(...switchedFallbackLoader, ...switchedLoader);
});
});

// Add new loader
const loader = currentFallbackLoader ?
Copy link
Member

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

addConditionalLoader(j, prodLoaders, devLoaders) :
j.arrayExpression(prodLoaders);

if (loaderPath) {
switch (loaderPath.type) {
case "CallExpression":
loaderPath.arguments = [loader];
break;
case "Property":
loaderPath.value = loader;
break;
case "ArrayExpression":
loaderIndex = elements.findIndex(e => e.callee && e.callee.object.name === "ExtractTextPlugin");
newElements = [
...elements.slice(0, loaderIndex),
loader,
...elements.slice(loaderIndex + 1)
];
loaderPath.elements = newElements;
break;
}
return p;
};
const name = utils.findVariableToPlugin(
j,
ast,
"extract-text-webpack-plugin"
);
if (!name) return ast;

return ast
.find(j.CallExpression)
.filter(p => findInvocation(j, p, name))
.forEach(changeArguments);
}

return ast;
};
4 changes: 3 additions & 1 deletion lib/migrate/extractTextPlugin/extractTextPlugin.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@

const defineTest = require("../../utils//defineTest");

defineTest(__dirname, "extractTextPlugin");
defineTest(__dirname, "extractTextPlugin", "extractTextPlugin-0");
defineTest(__dirname, "extractTextPlugin", "extractTextPlugin-1");
defineTest(__dirname, "extractTextPlugin", "extractTextPlugin-2");
Loading