UNPKG

roadhog-extra

Version:

Cli tool for serve and build react app, based on create-react-app, support JSON pattern config.

378 lines (355 loc) 9.02 kB
import webpack from 'webpack'; // import autoprefixer from 'autoprefixer'; import {existsSync} from 'fs'; import {join} from 'path'; import ExtractTextPlugin from 'extract-text-webpack-plugin'; import CopyWebpackPlugin from 'copy-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import normalizeDefine from '../utils/normalizeDefine'; import winPath from '../utils/winPath'; import runArray from "../utils/runArray"; export function getBabelOptions(config) { return { babelrc: false, presets: [ require.resolve('babel-preset-es2015'), require.resolve('babel-preset-react'), require.resolve('babel-preset-stage-0'), ].concat(config.extraBabelPresets || []), plugins: [ require.resolve('babel-plugin-add-module-exports'), require.resolve('babel-plugin-react-require'), require.resolve('babel-plugin-syntax-dynamic-import'), ].concat(config.extraBabelPlugins || []), cacheDirectory: true, }; } export const baseSvgLoader = (config) => { return { test: /\.svg$/, loader: 'file', options: { name: (config.assetsPath && config.assetsPath.img ? config.assetsPath.img : 'assets/img/' )+ '/[name].[hash:8].[ext]', }, } }; export const spriteSvgLoader = { test: /\.(svg)$/i, loader: 'svg-sprite', }; export const defaultDevtool = '#cheap-module-eval-source-map'; export function getResolve(config, paths) { return { resolve: { modules: [ paths.appNodeModules, paths.ownNodeModules, 'node_modules', ], extensions: [ ...(config.extraResolveExtensions || []), '.web.js', '.web.jsx', '.web.ts', '.web.tsx', '.js', '.json', '.jsx', '.ts', '.tsx', ], }, resolveLoader: { modules: [ paths.appNodeModules, paths.ownNodeModules, ], moduleExtensions: ['-loader'], }, }; } export function getFirstRules({config, paths, babelOptions}) { return [ { oneOf: [ { test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], loader: require.resolve('url-loader'), options: { limit: 10000, name: (config.assetsPath && config.assetsPath.img ? config.assetsPath.img : 'assets/img/' )+ '[name].[hash:8].[ext]', }, }, { exclude: [ /\.(html|ejs)$/, /\.(js|jsx)$/, /\.(css|less|scss|sass)$/, /\.json$/, /\.svg$/, /\.tsx?$/, ], loader: 'url', options: { limit: 10000, name: (config.assetsPath && config.assetsPath.media ? config.assetsPath.media : 'assets/media/') + '[name].[hash:8].[ext]', }, }, { test: /\.(js|jsx)$/, include: paths.appSrc, loader: 'babel', options: babelOptions, }, ] } ]; } export function getLastRules({paths, babelOptions}) { return [ { test: /\.html$/, loader: 'file', options: { name: '[name].[ext]', }, }, { test: /\.tsx?$/, include: paths.appSrc, use: [ { loader: 'babel', options: babelOptions, }, { loader: 'awesome-typescript', options: { transpileOnly: true, }, }, ], }, ]; } export function getCSSRules(env, {config, paths, cssLoaders, theme}) { function isExclude(modulePath) { if (config.cssModulesExclude && config.cssModulesExclude.length) { return config.cssModulesExclude.some((item) => { return winPath(join(paths.appDirectory, item)).indexOf(winPath(modulePath)) > -1; }); } return false; } function includeTest(root, modulePath) { return modulePath.indexOf(root) > -1 && !isExclude(modulePath); } let rules = [ { test: /\.css$/, include: includeTest.bind(null, paths.appSrc), use: [ require.resolve('style-loader'), ...cssLoaders.own, ], }, { test: /\.less$/, include: includeTest.bind(null, paths.appSrc), use: [ 'style', ...cssLoaders.own, { loader: 'less', options: { modifyVars: theme, }, }, ], }, { test: /\.css$/, include: includeTest.bind(null, paths.appNodeModules), use: [ require.resolve('style-loader'), ...cssLoaders.nodeModules, ], }, { test: /\.less$/, include: includeTest.bind(null, paths.appNodeModules), use: [ require.resolve('style-loader'), ...cssLoaders.nodeModules, { loader: 'less', options: { modifyVars: theme, }, }, ], }, ]; if (config.cssModulesExclude && config.cssModulesExclude.length) { const include = config.cssModulesExclude.map((item) => { return join(paths.appDirectory, item); }); rules = [ ...rules, { test: /\.css$/, include, use: [ require.resolve('style-loader'), ...cssLoaders.noCSSModules, ], }, { test: /\.less$/, include, use: [ require.resolve('style-loader'), ...cssLoaders.noCSSModules, { loader: 'less', options: { modifyVars: theme, }, }, ], }, ]; } if (config.sass) { const sassOptions = config.sass === true ? {} : config.sass; rules = [ ...rules, { test: /\.(scss|sass)$/, include: includeTest.bind(null, paths.appSrc), use: [ require.resolve('style-loader'), ...cssLoaders.own, { loader: 'sass', options: sassOptions, }, ], }, { test: /\.(scss|sass)$/, include: includeTest.bind(null, paths.appNodeModules), use: [ require.resolve('style-loader'), ...cssLoaders.nodeModules, { loader: 'sass', options: sassOptions, }, ], }, ]; if (config.cssModulesExclude && config.cssModulesExclude.length) { const include = config.cssModulesExclude.map((item) => { return join(paths.appDirectory, item); }); rules = [ ...rules, { test: /\.(scss|sass)$/, include, use: [ 'style', ...cssLoaders.noCSSModules, { loader: 'sass', options: sassOptions, }, ], }, ]; } } if (env === 'production') { rules.forEach((rule) => { rule.use = ExtractTextPlugin.extract({ // fallback: 'style', use: rule.use.slice(1), }); }); } return rules; } export const node = { fs: 'empty', net: 'empty', tls: 'empty', }; export function getCommonPlugins({config, paths, appBuild, NODE_ENV}) { const ret = []; let defineObj = { 'process.env': { NODE_ENV: JSON.stringify(NODE_ENV), }, }; if (config.define) { defineObj = { ...defineObj, ...normalizeDefine(config.define), }; } ret.push(new webpack.DefinePlugin(defineObj)); // HTML const defaultHtml = function () { ret.push(new HtmlWebpackPlugin()); } if (config.htmlTemplates) { if (config.htmlTemplates === true) { defaultHtml() } else { runArray(config.htmlTemplates, (h) => { ret.push(new HtmlWebpackPlugin(Object.assign({}, h))); }) } } else { defaultHtml() } let copyConfig = [] if(NODE_ENV === 'production' && config.copyConfig) { runArray(config.copyConfig, c => { copyConfig.push(c) }) } else { if (existsSync(paths.appPublic)) { copyConfig.push({ from: paths.appPublic, to: appBuild, }) } } if(copyConfig && copyConfig.length > 0) { ret.push(new CopyWebpackPlugin(copyConfig)); } if (config.multipage) { // Support hash const name = config.hash ? 'common.[hash]' : 'common'; ret.push(new webpack.optimize.CommonsChunkPlugin({ name: 'common', filename: (config.assetsPath && config.assetsPath.js ? config.assetsPath.js : 'assets/js/') + `${name}.js`, })); } if (config.ignoreMomentLocale) { ret.push(new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)); } /*ret.push(new webpack.LoaderOptionsPlugin({ options: { context: __dirname, postcss: [ autoprefixer(config.autoprefixer || { browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), ...(config.extraPostCSSPlugins ? config.extraPostCSSPlugins : []), ], }, }));*/ return ret; }