From 345b4f64b51025455dce57c6964ade9011481171 Mon Sep 17 00:00:00 2001 From: SteveSandersonMS Date: Fri, 27 Jan 2017 11:18:26 +0000 Subject: [PATCH] Update aspnet-webpack-react to support Webpack 2.x-style configs --- .../npm/aspnet-webpack-react/package.json | 4 +- .../src/HotModuleReplacement.ts | 57 ++++++++++++++++--- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json index 13d9b83..34150a9 100644 --- a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json +++ b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/package.json @@ -1,6 +1,6 @@ { "name": "aspnet-webpack-react", - "version": "1.0.3", + "version": "1.0.4", "description": "Helpers for using Webpack with React in ASP.NET Core projects. Works in conjunction with the Microsoft.AspNetCore.SpaServices NuGet package.", "main": "index.js", "scripts": { @@ -26,7 +26,7 @@ "react-transform-hmr": "^1.0.4" }, "devDependencies": { - "@types/webpack": "^1.12.34", + "@types/webpack": "^2.2.0", "rimraf": "^2.5.4", "typescript": "^2.0.0", "webpack": "^1.12.14" diff --git a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts index 3b77a36..b1787de 100644 --- a/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts +++ b/src/Microsoft.AspNetCore.SpaServices/npm/aspnet-webpack-react/src/HotModuleReplacement.ts @@ -1,17 +1,58 @@ import * as webpack from 'webpack'; +type OldOrNewModule = webpack.OldModule & webpack.NewModule; export function addReactHotModuleReplacementBabelTransform(webpackConfig: webpack.Configuration) { - const moduleRules: webpack.Loader[] = - (webpackConfig.module as any).rules // Webpack < 2.1.0 beta 23 - || webpackConfig.module.loaders; // Webpack >= 2.1.0 beta 23 + const moduleConfig = webpackConfig.module as OldOrNewModule; + const moduleRules = moduleConfig.rules // Webpack >= 2.1.0 beta 23 + || moduleConfig.loaders; // Legacy/back-compat + if (!moduleRules) { + return; // Unknown rules list format + } - moduleRules.forEach(loaderConfig => { - if (loaderConfig.loader && loaderConfig.loader.match(/\bbabel-loader\b/)) { - // Ensure the babel-loader options includes a 'query' - const query = loaderConfig.query = loaderConfig.query || {}; + moduleRules.forEach(rule => { + // Allow rules/loaders entries to be either { loader: ... } or { use: ... } + // Ignore other config formats (too many combinations to support them all) + let loaderConfig = + (rule as webpack.NewUseRule).use // Recommended config format for Webpack 2.x + || (rule as webpack.LoaderRule).loader; // Typical config format for Webpack 1.x + if (!loaderConfig) { + return; // Not a supported rule format (e.g., an array) + } + + // Allow use/loader values to be either { loader: 'name' } or 'name' + // We don't need to support other possible ways of specifying loaders (e.g., arrays), + // so skip unrecognized formats. + const loaderNameString = + (loaderConfig as (webpack.OldLoader | webpack.NewLoader)).loader + || (loaderConfig as string); + if (!loaderNameString || (typeof loaderNameString !== 'string')) { + return; // Not a supported loader format (e.g., an array) + } + + // Find the babel-loader entry + if (loaderNameString.match(/\bbabel-loader\b/)) { + // If the rule is of the form { use: 'name' }, then replace it + // with { use: { loader: 'name' }} so we can attach options + if ((rule as webpack.NewUseRule).use && typeof loaderConfig === 'string') { + loaderConfig = (rule as webpack.NewUseRule).use = { loader: loaderConfig }; + } + + const configItemWithOptions = typeof loaderConfig === 'string' + ? rule // The rule is of the form { loader: 'name' }, so put options on the rule + : loaderConfig; // The rule is of the form { use/loader: { loader: 'name' }}, so put options on the use/loader + + // Ensure the config has an 'options' (or a legacy 'query') + let optionsObject = + (configItemWithOptions as webpack.NewLoader).options // Recommended config format for Webpack 2.x + || (configItemWithOptions as webpack.OldLoaderRule).query; // Legacy + if (!optionsObject) { + // If neither options nor query was set, define a new value, + // using the legacy format ('query') for compatibility with Webpack 1.x + optionsObject = (configItemWithOptions as webpack.OldLoaderRule).query = {}; + } // Ensure Babel plugins includes 'react-transform' - const plugins = query['plugins'] = query['plugins'] || []; + const plugins = optionsObject['plugins'] = optionsObject['plugins'] || []; const hasReactTransform = plugins.some(p => p && p[0] === 'react-transform'); if (!hasReactTransform) { plugins.push(['react-transform', {}]);