UNPKG

ecology9-src4js-tools

Version:

src4js-tools

478 lines (440 loc) 16 kB
const { injectBabelPlugin, getLoader, paths } = require('./config/react-app-rewired'); const webpack = require('webpack'); const path = require('path'); const fs = require('fs'); // const url = require('url'); const argv = require('yargs').argv; const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); const SWPrecacheWebpackPlugin = require('sw-precache-webpack-plugin'); const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); // 用于替换 SWPrecacheWebpackPlugin const ExtractTextPlugin = require('extract-text-webpack-plugin'); const FileManagerPlugin = require('filemanager-webpack-plugin'); // 压缩打包后的本地化应用包 const HtmlWebpackHandleCssInjectPlugin = require('./config/webpack-theme-plugin'); const styleLoaders = [{ loader: require.resolve('css-loader'), options: { importLoaders: 1, minimize: true, sourceMap: true, } }, { loader: require.resolve('less-loader'), }]; const resolveToThemeStaticPath = fileName => path.resolve(paths.appThemePath, fileName); const themeFileNameSet = fs.readdirSync(path.resolve(paths.appThemePath)); const themePaths = themeFileNameSet.map(resolveToThemeStaticPath); const getThemeName = fileName => `${path.basename(fileName, path.extname(fileName))}`; const themesExtractLessSet = themeFileNameSet.map(fileName => new ExtractTextPlugin({ filename: `static/css/${getThemeName(fileName)}.css?v=[contenthash:8]`, allChunks: true })); const themeLoaderSet = themeFileNameSet.map((fileName, index) => { // console.log("fileName dd:",fileName," i:",index," resolveToThemeStaticPath(fileName):",resolveToThemeStaticPath(fileName)); return { test: /\.(less|css)$/, include: resolveToThemeStaticPath(fileName), loader: themesExtractLessSet[index].extract({ use: styleLoaders }) } }); const lessToJs = require('less-vars-to-js'); const wmThemeDefaultPath = resolveApp('node_modules/weaver-mobile/lib/style/themes/default.less'); const wmThemeDefaulPaletteLess = fs.readFileSync(wmThemeDefaultPath, 'utf8'); const themelessVarsToJsDefault = lessToJs(wmThemeDefaulPaletteLess, { resolveVariables: true, stripPrefix: true }); const themelessVarsToJs = {}; themeFileNameSet.forEach(fileName => { const paletteLess = fs.readFileSync(resolveToThemeStaticPath(fileName), 'utf8'); const originLess = Object.assign({}, themelessVarsToJsDefault, lessToJs(paletteLess, { resolveVariables: true, stripPrefix: true })); const result = { hd: eval(originLess.hd.replace('px', '')) }; Object.keys(originLess).forEach(l => { const reg = /\s\*\s@hd$/; if (originLess[l].match(reg)) { result[l] = eval(`${originLess[l].replace(reg, '')}*${result.hd}`); } }) themelessVarsToJs[getThemeName(fileName)] = Object.assign({}, result, { less: originLess }); }); const fileLoaderMatcher = function (rule) { return rule.loader && rule.loader.indexOf(`file-loader`) != -1; } module.exports = function override(config, env) { if (env === 'production') { // console.log(config.plugins[config.plugins.length-1]); // console.log(config.entry); // config.entry = [require.resolve('./polyfills'), config.entry[1]]; config.entry = { pre: [ require.resolve('./polyfills'), 'react', 'react-dom', 'mobx', 'mobx-react', require.resolve(argv.local ? './pre_local.js' : './pre.js'), ], main: config.entry[1], dev: require.resolve('./devComponent.js'), }; var n = config.plugins.length; config.plugins[n] = new HtmlWebpackHandleCssInjectPlugin({ themelessVarsToJs, paths, filter: (filePath) => { return filePath.includes('theme'); } }); themesExtractLessSet.map((obj, i) => { config.plugins[n + (i + 1)] = obj; }); config.module.rules[1].oneOf.unshift( { test: /\.less$/, exclude: paths.appThemePath, loader: ExtractTextPlugin.extract( Object.assign( { fallback: { loader: require.resolve('style-loader'), options: { hmr: false, }, }, use: styleLoaders } ) ) } ); // css-modules config.module.rules[1].oneOf.unshift( { test: /\.css$/, exclude: paths.appThemePath, loader: ExtractTextPlugin.extract( Object.assign( { fallback: { loader: require.resolve('style-loader'), options: { hmr: false, }, }, use: styleLoaders } ) ), } ); themeLoaderSet.map((obj) => { config.module.rules[1].oneOf.unshift(obj); }); // config.output.filename = 'static/js/main.js?v=[hash:8]'; config.output.filename = `static/js/[name].js?v=[hash:8]`; config.output.chunkFilename = `static/js/[name].chunk.js?v=[chunkhash:8]`; config.plugins[4] = new ExtractTextPlugin({ filename: `static/css/[name].css?v=[contenthash:8]`, }); if (argv.analyzer === 'true') { config.plugins.push(new BundleAnalyzerPlugin()); } config.plugins.push( new webpack.optimize.CommonsChunkPlugin({ name: 'pre', filename: `static/js/[name].js?v=[hash:8]`, }) ); if (argv.local) { const appBuildPath = paths.appBuild.replace(/\\/g, '/'); const index = appBuildPath.indexOf('/static') === -1 ? appBuildPath.indexOf('/sso') : appBuildPath.indexOf('/static'); const sourcePath = appBuildPath.substr(0, index); const moduleName = sourcePath.substr(sourcePath.lastIndexOf('/') + 1); config.plugins.push( new FileManagerPlugin({ onEnd: [ { copy: [ { source: sourcePath, destination: '../spaLocal/zip/' + moduleName } ], archive: [ { source: `../spaLocal/zip`, destination: `../spaLocal/${moduleName}.zip` } ], delete: [ `../spaLocal/zip` ] } ] }) ) } } else { config.module.rules[1].oneOf.unshift( { test: /\.less$/, use: [ require.resolve('style-loader'), require.resolve('css-loader'), { loader: require.resolve('postcss-loader'), options: { // Necessary for external CSS imports to work // https://github.com/facebookincubator/create-react-app/issues/2677 ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), ], }, }, { loader: require.resolve('less-loader'), options: { // theme vars, also can use theme.js instead of this. // modifyVars: { "@brand-primary": "#1DA57A" }, }, }, ] } ); // css-modules config.module.rules[1].oneOf.unshift( { test: /\.css$/, exclude: /node_modules|weaver-mobile\.css/, use: [ require.resolve('style-loader'), { loader: require.resolve('css-loader'), options: { modules: true, importLoaders: 1, localIdentName: '[local]___[hash:base64:5]' }, }, { loader: require.resolve('postcss-loader'), options: { // Necessary for external CSS imports to work // https://github.com/facebookincubator/create-react-app/issues/2677 ident: 'postcss', plugins: () => [ require('postcss-flexbugs-fixes'), autoprefixer({ browsers: [ '>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9', // React doesn't support IE8 anyway ], flexbox: 'no-2009', }), ], }, }, ] } ); config.plugins.push( new HtmlWebpackHandleCssInjectPlugin({ isDev: true, themelessVarsToJs, filter: (filePath) => { return filePath.includes('theme'); } }) ); if (argv.local) { const appBuildPath = paths.appBuild.replace(/\\/g, '/'); const index = appBuildPath.indexOf('/static') === -1 ? appBuildPath.indexOf('/sso') : appBuildPath.indexOf('/static'); const sourcePath = appBuildPath.substr(0, index); const moduleName = sourcePath.substr(sourcePath.lastIndexOf('/') + 1); config.plugins.push( new FileManagerPlugin({ onEnd: [ { copy: [ { source: sourcePath, destination: '../spaLocal/zip/' + moduleName } ], archive: [ { source: `../spaLocal/zip`, destination: `../spaLocal/${moduleName}.zip` } ], delete: [ `../spaLocal/zip` ] } ] }) ) } } config.module.rules[1].oneOf.unshift({ test: /\.(js|jsx)$/, include: paths.appSrc, loader: require.resolve('babel-loader'), exclude: /node_modules(\/|\\)(?!weaver-mobile-page)/, options: { // @remove-on-eject-begin babelrc: false, plugins: [ [require.resolve('babel-plugin-transform-runtime')], [require.resolve('babel-plugin-transform-decorators-legacy')], [require.resolve('babel-plugin-import'), [{ libraryName: 'weaver-mobile', //style: 'css', // style: true, // use less for customized theme }, { libraryName: 'weaver-mobile-page', libraryDirectory: 'es', //style: 'css', // style: true, // use less for customized theme }]], ], presets: [ require.resolve('babel-preset-es2015'), require.resolve('babel-preset-stage-0'), require.resolve('babel-preset-react') ], //require.resolve('babel-preset-react-app'), // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, }, }); config.module.rules[1].oneOf.unshift({ test: /\.(js|jsx)$/, include: /(pre|registerServiceWorker).js/, loader: require.resolve('babel-loader'), exclude: /node_modules(\/|\\)(?!weaver-mobile-page)/, options: { // @remove-on-eject-begin babelrc: false, plugins: [ [require.resolve('babel-plugin-transform-runtime')], [require.resolve('babel-plugin-transform-decorators-legacy')], [require.resolve('babel-plugin-import'), [{ libraryName: 'weaver-mobile', //style: 'css', // style: true, // use less for customized theme }, { libraryName: 'weaver-mobile-page', libraryDirectory: 'es', //style: 'css', // style: true, // use less for customized theme }]], ], presets: [ require.resolve('babel-preset-es2015'), require.resolve('babel-preset-stage-0'), require.resolve('babel-preset-react') ], //require.resolve('babel-preset-react-app'), // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, }, }); config.module.rules[1].oneOf.unshift({ test: /\.(js|jsx)$/, include: /devComponent.js/, loader: require.resolve('babel-loader'), exclude: /node_modules(\/|\\)(?!weaver-mobile-page)/, options: { // @remove-on-eject-begin babelrc: false, plugins: [ [require.resolve('babel-plugin-transform-runtime')], [require.resolve('babel-plugin-transform-decorators-legacy')], [require.resolve('babel-plugin-import'), [{ libraryName: 'weaver-mobile', //style: 'css', // style: true, // use less for customized theme }, { libraryName: 'weaver-mobile-page', libraryDirectory: 'es', //style: 'css', // style: true, // use less for customized theme }]], ], presets: [ require.resolve('babel-preset-es2015'), require.resolve('babel-preset-stage-0'), require.resolve('babel-preset-react') ], //require.resolve('babel-preset-react-app'), // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, }, }); config.module.rules[1].oneOf.unshift({ test: /\.(js|jsx)$/, include: /node_modules(\/|\\)weaver-mobile-page/, loader: require.resolve('babel-loader'), options: { // @remove-on-eject-begin babelrc: false, plugins: [ [require.resolve('babel-plugin-transform-runtime')], [require.resolve('babel-plugin-transform-decorators-legacy')], [require.resolve('babel-plugin-import'), { libraryName: 'weaver-mobile', //style: 'css', // style: true, // use less for customized theme }], ], presets: [ require.resolve('babel-preset-es2015'), require.resolve('babel-preset-stage-0'), require.resolve('babel-preset-react') ], //require.resolve('babel-preset-react-app'), // @remove-on-eject-end // This is a feature of `babel-loader` for webpack (not Babel itself). // It enables caching results in ./node_modules/.cache/babel-loader/ // directory for faster rebuilds. cacheDirectory: true, } }); config.resolve.plugins = []; config.plugins = config.plugins.map(p => { if (p instanceof SWPrecacheWebpackPlugin) { return argv.local ? () => { } : new WorkboxWebpackPlugin.GenerateSW({ clientsClaim: true, exclude: [/\.map$/, /asset-manifest\.json$/], importWorkboxFrom: 'disabled', navigateFallback: paths.servedPath + 'index.html', importScripts: ['/cloudstore/resource/mobile/workbox-v4.3.1/workbox-sw.js'], navigateFallbackBlacklist: [ // Exclude URLs starting with /_, as they're likely an API call new RegExp('^/_'), // Exclude URLs containing a dot, as they're likely a resource in // public/ and not a SPA route new RegExp('/[^/]+\\.[^/]+$'), ], precacheManifestFilename: 'precache-manifest.js?v=[manifestHash]', skipWaiting: true, }) } return p; }) config.externals = argv.local ? [{ '$': '$' }, { 'jquery': 'jQuery' }, { 'jQuery': 'jQuery' }, { 'loadjs': 'loadjs' }] : [{ '$': '$' }, { 'jquery': 'jQuery' }, { 'jQuery': 'jQuery' }]; // file-loader exclude let l = getLoader(config.module.rules, fileLoaderMatcher); l.exclude.push(/\.less$/); config.resolve.alias = Object.assign({}, config.resolve.alias, { 'mobx-react': 'wm-mobx-react', 'react-router': 'wm-react-router', }); return config; };