UNPKG

tix-react-ssr

Version:

Tiket.com React Project Scripts

401 lines (356 loc) 11 kB
const fs = require('fs'); const path = require('path'); const webpack = require('webpack'); const StyleLintPlugin = require('stylelint-webpack-plugin'); const AssetsPlugin = require('assets-webpack-plugin'); const nodeExternals = require('webpack-node-externals'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); const workboxPlugin = require('workbox-webpack-plugin'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const multi = require('multi-loader'); const paths = require('../config/paths'); const config = require('config').util.loadFileConfigs(paths.appPath + '/config'); const pkg = require('../package.json'); const progressHandler = require('./progress'); const { argv, env : { NODE_ENV, SOURCE_MAP, DEV_SERVER, ALLOW_CONSOLE } } = process; const isDevEnv = NODE_ENV !== 'production'; const isDevServer = !!DEV_SERVER; const useSourceMap = SOURCE_MAP !== 'false'; const isVerbose = argv.includes('--verbose'); const isAnalyze = argv.includes('--analyze') || argv.includes('--analyse'); console.log('Building webpack isDevServer: ' + isDevServer + ', isDevEnv: ' + isDevEnv + ', useSourceMap: ' + useSourceMap); // // Common configuration chunk to be used for both // client-side (client.js) and server-side (server.js) bundles // ----------------------------------------------------------------------------- const webpackConfig = ({ isClient }) => ({ output: { path: paths.appBuild + '/public/assets/', publicPath: config.compiler_public_path || '/assets/', pathinfo: isVerbose }, resolve: { extensions: ['.js', '.jsx'], alias: { build: paths.appBuild } }, module: { rules: [ { test: /\.jsx?$/, exclude: (modulePath)=>{ return /node_modules/.test(modulePath) && !/node_modules|@tiketdotcom/.test(modulePath); }, use: [ { loader: 'babel-loader', options: { babelrc: false, presets: [ [ 'env', { targets: { ...(!isClient ? { node: pkg.engines.node.match(/(\d+\.?)+/)[0] } : { browsers: pkg.browserslist }), }, modules: false, useBuiltIns: true, }, ], 'stage-0', 'react', ...(isDevServer ? [] : ['react-optimize']), ], plugins: [ 'lodash', 'transform-regenerator', 'transform-decorators-legacy' ], }, }, ], }, { test: /\.(graphql|gql)$/, use: ['graphql-tag/loader'], }, { test: /\.(eot|ttf|woff|woff2)$/, use: [ { loader: 'url-loader', options: { limit: 1024, emitFile: isClient, }, }, ], }, { test: /\.(png|jpe?g)$/i, use: multi( `file-loader?name=${isDevServer ? '[name].[ext]' : '[name].[ext]'}.webp!webp-loader?{quality: 95}`, `file-loader?name=${isDevServer ? '[name].[ext]' : '[name].[ext]'}` ), }, { test: /\.(gif|svg)$/i, use: [ { loader: 'file-loader', options: { limit: 1024, name: isDevServer ? '[name].[ext]' : '[hash:8].[ext]', emitFile: isClient, }, }, ], }, // Exclude dev modules from production build ...isDevServer ? [] : [ { test: path.resolve(__dirname, '../node_modules/react-deep-force-update/lib/index.js'), use: 'null-loader', }, ], ], }, plugins: [ new webpack.ProgressPlugin({ handler: progressHandler }), new StyleLintPlugin({ configFile: paths.appPath + '/.stylelintrc', syntax: 'scss' }) ], // Don't attempt to continue if there are any errors. bail: !isDevEnv, cache: isDevEnv, stats: 'minimal' }); const styleLoaders = ({ isClient }) => [ { loader: `css-loader${isClient ? '' : '/locals'}`, options: { minimize: !isDevEnv, module: false, importLoaders: 2, }, }, { loader: 'postcss-loader', options: { config: { path: path.resolve(__dirname, './postcss.config.js') } }, }, { loader: 'sass-loader' }, ]; // // Configuration for the client-side bundle (client.js) // ----------------------------------------------------------------------------- const baseClientConfig = webpackConfig({ isClient: true }); const clientConfig = { ...baseClientConfig, name: 'client', target: 'web', performance: { hints: !isDevEnv ? 'warning' : false, assetFilter: assetFilename => !/\.map|server.js$/.test(assetFilename), }, entry: { client: [ 'babel-polyfill', path.resolve(__dirname, './polyfills.js'), paths.appSrc + '/client.js', ] }, output: { ...baseClientConfig.output, filename: isDevServer ? '[name].js' : '[name].[chunkhash:8].js', chunkFilename: isDevServer ? '[name].chunk.js' : '[name].[chunkhash:8].chunk.js', crossOriginLoading: 'anonymous', libraryTarget: 'umd', }, module: { rules: [ ...baseClientConfig.module.rules, { test: /\.s?css$/, use: ExtractTextPlugin.extract({ fallback: 'style-loader', use: styleLoaders({ isClient: true }), allChunks: true }), } ] }, plugins: [ ...baseClientConfig.plugins, // Define free variables // https://webpack.github.io/docs/list-of-plugins.html#defineplugin new webpack.DefinePlugin({ CONFIG: JSON.stringify(config.globals), 'process.env.DEV_SERVER': isDevServer, 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV), 'process.env.BROWSER': true, __DEVTOOLS__: isVerbose // <-------- DISABLE redux-devtools HERE }), // Move modules that occur in multiple entry chunks to a new entry chunk (the commons chunk). // http://webpack.github.io/docs/list-of-plugins.html#commonschunkplugin new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', minChunks: module => module.context && module.context.includes('node_modules'), }), new ExtractTextPlugin({ filename: isDevServer ? '[name].css' : '[name].[contenthash:8].css', allChunks: true, disable: isDevServer }), ...(isDevServer ? [] : [ new webpack.optimize.ModuleConcatenationPlugin(), // Minimize all JavaScript output of chunks // https://github.com/mishoo/UglifyJS2#compressor-options new webpack.optimize.UglifyJsPlugin({ sourceMap: useSourceMap, compress: { screw_ie8: true, // React doesn't support IE8 warnings: isVerbose, unused: true, dead_code: true, drop_console: !ALLOW_CONSOLE }, mangle: { screw_ie8: true, }, output: { comments: false, screw_ie8: true, beautify: false }, }) ]), // Emit a file with assets paths // https://github.com/sporto/assets-webpack-plugin#options new AssetsPlugin({ path: paths.appBuild, filename: 'assets.json' }), // load `moment/locale/ja.js` and `moment/locale/it.js` new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /id|en-gb/), // Webpack Bundle Analyzer // https://github.com/th0r/webpack-bundle-analyzer ...isAnalyze ? [new BundleAnalyzerPlugin()] : [], new workboxPlugin.GenerateSW({ cacheId: 'tiket-sw-cache-v1', swDest: 'service-worker.js', clientsClaim: true, skipWaiting: true, importWorkboxFrom: 'local', ignoreUrlParametersMatching: [/./], runtimeCaching: [ { urlPattern: /^https:\/\/tixcore\.netlify\.com/, handler: 'staleWhileRevalidate', options: { cacheName: 'core-libs' } }, { urlPattern: /^https:\/\/[a-z0-9]+\.tiket\.com\/(assets_version|images)\//, handler: 'cacheFirst', options: { cacheName: 'tiket' } } ] }) ], // Choose a developer tool to enhance debugging // http://webpack.github.io/docs/configuration.html#devtool devtool: isDevEnv && useSourceMap ? 'cheap-module-source-map' : false, // Some libraries const Node modules but don't use them in the browser. // Tell Webpack to provide empty mocks for them so importing them works. // https://webpack.github.io/docs/configuration.html#node // https://github.com/webpack/node-libs-browser/tree/master/mock node: { fs: 'empty', net: 'empty', tls: 'empty', }, }; // // Configuration for the server-side bundle (server.js) // ----------------------------------------------------------------------------- const baseServerConfig = webpackConfig({ isClient: false }); const serverConfig = { ...baseServerConfig, name: 'server', target: 'node', devtool: isDevEnv && useSourceMap ? 'source-map' : false, performance: false, entry: { server: ['babel-polyfill', paths.appSrc + '/server.js'], }, output: { ...baseServerConfig.output, path: paths.appBuild, filename: '[name].js', libraryTarget: 'commonjs2', }, module: { ...baseServerConfig.module, // Override babel-preset-env configuration for Node.js rules:[ ...baseServerConfig.module.rules, { test: /\.s?css$/, use: styleLoaders({ isClient: false }), }, ], }, externals: [ /^\.\/assets\.json$/, nodeExternals({ whitelist: /(@tiketdotcom|tix-react-ssr|\.(css|less|scss|sss)$)/i}), ], plugins: [ ...baseServerConfig.plugins, new ExtractTextPlugin({ filename: 'styles.css', allChunks: true, disable: isDevServer }), // Define free variables // https://webpack.github.io/docs/list-of-plugins.html#defineplugin new webpack.DefinePlugin({ CONFIG: JSON.stringify(config.globals), 'process.env.DEV_SERVER': isDevServer, 'process.env.BROWSER': false, __DEVTOOLS__: isVerbose // <-------- DISABLE redux-devtools HERE }), // Do not create separate chunks of the server bundle // https://webpack.github.io/docs/list-of-plugins.html#limitchunkcountplugin new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }), new webpack.BannerPlugin({ banner: 'require("source-map-support").install();', raw: true, entryOnly: false, }) ], node: { console: false, global: false, process: false, Buffer: false, __filename: false, __dirname: false, } }; const configs = [clientConfig, serverConfig]; module.exports = configs;