├── transforms ├── __testfixtures__ │ ├── rootToModules.output.js │ ├── rootToModules.input.js │ ├── loaderSyntax.input.js │ └── loaderSyntax.output.js ├── __tests__ │ ├── loaderSyntax-test.js │ └── rootToModules-test.js ├── rootToModules.js └── loaderSyntax.js ├── README.md ├── .gitignore ├── package.json └── LICENSE /transforms/__testfixtures__/rootToModules.output.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | modules: [path.join(__dirname, "src"), "node_modules"] 3 | } 4 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/rootToModules.input.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: path.join(__dirname, "src"), 3 | modules: ["node_modules"] 4 | } 5 | -------------------------------------------------------------------------------- /transforms/__tests__/loaderSyntax-test.js: -------------------------------------------------------------------------------- 1 | const defineTest = require('jscodeshift/dist/testUtils').defineTest; 2 | defineTest(__dirname, 'loaderSyntax'); 3 | -------------------------------------------------------------------------------- /transforms/__tests__/rootToModules-test.js: -------------------------------------------------------------------------------- 1 | const defineTest = require('jscodeshift/dist/testUtils').defineTest; 2 | defineTest(__dirname, 'rootToModules'); 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-codemods 2 | [JSCodeshift](https://github.com/facebook/jscodeshift) Codemods to automatically convert webpack config from v1 to v2 3 | 4 | 🚧🚧🚧🚧🚧🚧 5 | 6 | This repository is deprecated in favor of https://github.com/webpack/webpack-cli where I continue to work on it. You can follow it here: https://github.com/webpack/webpack-cli/pull/40 7 | 8 | 🚧🚧🚧🚧🚧🚧 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-codemods", 3 | "version": "1.0.0", 4 | "description": "JS Codemod to automatically convert webpack config from v1 to v2", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jest" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/okonet/webpack-codemods.git" 12 | }, 13 | "keywords": [], 14 | "author": "Andrey Okonetchnikov ", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/okonet/webpack-codemods/issues" 18 | }, 19 | "homepage": "https://github.com/okonet/webpack-codemods#readme", 20 | "devDependencies": { 21 | "jest": "^18.1.0" 22 | }, 23 | "dependencies": { 24 | "jscodeshift": "^0.3.30" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Andrey Okonetchnikov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/loaderSyntax.input.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | loaders: [ 4 | // Extended syntax 5 | { 6 | test: /\.css$/, 7 | loaders: [ 8 | { 9 | loader: "style-loader" 10 | }, 11 | { 12 | loader: "css-loader", 13 | query: { 14 | modules: true 15 | } 16 | } 17 | ] 18 | }, 19 | // Automatic -loader module name extension 20 | { 21 | test: /\.scss$/, 22 | use: [ 23 | "style", 24 | "css", 25 | "scss" 26 | ] 27 | }, 28 | // Query params syntax 29 | { 30 | test: /\.scss$/, 31 | loaders: ["style-loader", "css-loader?modules&importLoaders=1"] 32 | }, 33 | // Chaining loaders 34 | { 35 | test: /\.pcss$/, 36 | use: "style-loader!css-loader!postcss-loader" 37 | }, 38 | // Function syntax 39 | { 40 | test: /\.pcss$/, 41 | loader: ExtractTextPlugin.extract("style-loader", "css-loader", { publicPath: "/dist" }) 42 | } 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /transforms/rootToModules.js: -------------------------------------------------------------------------------- 1 | module.exports = function transformer(file, api) { 2 | const j = api.jscodeshift; 3 | const ast = j(file.source); 4 | 5 | const webpackConfig = ast.find(j.ObjectExpression) 6 | 7 | let rootVal; 8 | webpackConfig 9 | .find(j.Identifier, { name: 'root' }) 10 | .forEach(path => { 11 | rootVal = path.parent.value; 12 | }) 13 | 14 | function findOrCreateModulesObjectExpression(ast) { 15 | let modulesIdent = webpackConfig 16 | .find(j.Property, { key: { name: 'modules' }}) 17 | 18 | if (modulesIdent.size() === 0) { 19 | modulesIdent = webpackConfig 20 | .find(j.Property, { key: {name: 'root' }}) 21 | .paths()[0].parent 22 | } 23 | 24 | return modulesIdent 25 | } 26 | 27 | if (rootVal) { 28 | const val = rootVal.value 29 | 30 | webpackConfig 31 | .find(j.Identifier, { name: 'root' }) 32 | .forEach(path => { 33 | j(path.parent).remove() 34 | }) 35 | 36 | return findOrCreateModulesObjectExpression(ast) 37 | .forEach(path => { 38 | path.get('value').node.elements.unshift(val) 39 | }) 40 | .toSource(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /transforms/__testfixtures__/loaderSyntax.output.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | module: { 3 | rules: [ 4 | // Extended syntax 5 | { 6 | test: /\.css$/, 7 | use: [ 8 | { 9 | loader: "style-loader" 10 | }, 11 | { 12 | loader: "css-loader", 13 | query: { 14 | modules: true 15 | } 16 | } 17 | ] 18 | }, 19 | // Automatic -loader module name extension 20 | { 21 | test: /\.scss$/, 22 | use: [ 23 | "style-loader", 24 | "css-loader", 25 | "scss-loader" 26 | ] 27 | }, 28 | // Query params syntax 29 | { 30 | test: /\.scss$/, 31 | use: ["style-loader", "css-loader?modules&importLoaders=1"] 32 | }, 33 | // Chaining loaders 34 | { 35 | test: /\.pcss$/, 36 | use: ["style-loader", "css-loader", "postcss-loader"] 37 | }, 38 | // Function syntax 39 | { 40 | test: /\.pcss$/, 41 | loader: ExtractTextPlugin.extract({ 42 | fallbackLoader: "style-loader", 43 | loader: "css-loader", 44 | publicPath: "/dist" 45 | }) 46 | } 47 | ] 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /transforms/loaderSyntax.js: -------------------------------------------------------------------------------- 1 | module.exports = function transformer(file, api) { 2 | const j = api.jscodeshift; 3 | const ast = j(file.source); 4 | 5 | // Convert `query` to `options` 6 | ast 7 | .find(j.Identifier, { name: 'query' }) 8 | .forEach(path => { 9 | j(path).replaceWith(j.identifier('options')) 10 | }) 11 | 12 | // Convert `loaders` to `use` 13 | const loadersPaths = ast 14 | .find(j.Identifier, { name: 'loaders' }) 15 | 16 | loadersPaths 17 | .filter(path => { 18 | const keys = path.parent.parent.node.properties.map(p => p.key.name) 19 | return keys.indexOf('test') > -1 20 | //return true 21 | }) 22 | .forEach(path => { 23 | j(path).replaceWith(j.identifier('use')) 24 | }); 25 | 26 | // Convert `loaders` to `rules` 27 | loadersPaths 28 | .filter(path => { 29 | const keys = path.parent.parent.node.properties.map(p => p.key.name) 30 | return keys.indexOf('test') < 0 31 | }) 32 | .forEach(path => { 33 | j(path).replaceWith(j.identifier('rules')) 34 | }); 35 | 36 | // Chaining loaders 37 | ast 38 | .find(j.Property, { key: { name: 'use' } }) 39 | .filter(path => path.node.value.type === j.Literal.name) 40 | .map(path => path.get('value')) 41 | .forEach(path => { 42 | const loadersArray = path.value.value.split('!') 43 | j(path).replaceWith( 44 | j.arrayExpression( 45 | loadersArray.map(loader => j.literal(loader)) 46 | ) 47 | ) 48 | }); 49 | return ast.toSource() 50 | } 51 | --------------------------------------------------------------------------------