diff options
Diffstat (limited to 'front/odiparpack/internals/webpack')
4 files changed, 561 insertions, 0 deletions
| diff --git a/front/odiparpack/internals/webpack/webpack.base.babel.js b/front/odiparpack/internals/webpack/webpack.base.babel.js new file mode 100644 index 0000000..ca26c12 --- /dev/null +++ b/front/odiparpack/internals/webpack/webpack.base.babel.js @@ -0,0 +1,205 @@ +/** + * COMMON WEBPACK CONFIGURATION + */ + +const path = require('path'); +const webpack = require('webpack'); + +const HappyPack = require('happypack'); +const happyThreadPool = HappyPack.ThreadPool({ size: 5 }); + +module.exports = options => ({ +  mode: options.mode, +  entry: options.entry, +  output: Object.assign( +    { +      // Compile into js/build.js +      path: path.resolve(process.cwd(), 'build'), +      publicPath: '/', +    }, +    options.output, +  ), // Merge with env dependent settings +  devServer: { +    inline: false, +  }, +  optimization: options.optimization, +  module: { +    rules: [ +      /* +        Disabled eslint by default. +        You can enable it to maintain and keep clean your code. +        NOTE: By enable eslint running app process at beginning will slower +      */ +      //      { +      //        enforce: 'pre', +      //        test: /\.js?$/, +      //        exclude: [/node_modules/], +      //        loader: 'eslint-loader', +      //        options: { +      //          quiet: true +      //        } +      //      }, +      { +        test: /\.jsx?$/, // Transform all .js files required somewhere with Babel +        exclude: /node_modules/, +        use: { +          loader: 'happypack/loader?id=js', +          options: options.babelQuery, +        }, +      }, +      { +        // Preprocess our own .css files +        // This is the place to add your own loaders (e.g. sass/less etc.) +        // for a list of loaders, see https://webpack.js.org/loaders/#styling +        test: /\.css$/, +        exclude: /node_modules/, +        use: ['style-loader', 'css-loader'], +      }, +      { +        // Preprocess 3rd party .css files located in node_modules +        test: /\.css$/, +        include: /node_modules/, +        use: ['style-loader', 'css-loader'], +      }, +      { +        test: /\.(eot|otf|ttf|woff|woff2)$/, +        use: 'file-loader', +      }, +      { +        test: /\.(scss)$/, +        use: [{ +          loader: 'style-loader' +        }, +        { +          loader: 'css-loader', +          options: +          { +            sourceMap: false, +            importLoaders: 2, +            modules: true, +            localIdentName: '[local]__[hash:base64:5]' +          } +        }, +        { +          loader: 'postcss-loader', +          options: { +            sourceMap: false +          } +        }, +        { +          loader: 'sass-loader', +          options: { +            outputStyle: 'expanded', +            sourceMap: false +          } +        }], +      }, +      { +        test: /\.md$/, +        use: 'raw-loader' +      }, +      { +        test: /\.(jpg|png|gif|svg)$/, +        use: [ +          { +            loader: 'url-loader', +            options: { +              // Inline files smaller than 10 kB +              limit: 10 * 1024, +            }, +          }, +          /* +            Disabled image compression by default, +            due error in windows 10 because libpng not available. +            The libpng avaible on Linux and Mac system only. +            NOTE: To enable this, first you need to install image-webpack-loader. +            npm install -i image-webpack-loader --save +          */ +          //  { +          //    loader: 'image-webpack-loader', +          //    options: { +          //      mozjpeg: { +          //        enabled: false, +          //        // NOTE: mozjpeg is disabled as it causes errors in some Linux environments +          //        // Try enabling it in your environment by switching the config to: +          //        // enabled: true, +          //        // progressive: true, +          //      }, +          //      gifsicle: { +          //        interlaced: false, +          //      }, +          //      optipng: { +          //        optimizationLevel: 7, +          //      }, +          //      pngquant: { +          //        quality: '65-90', +          //        speed: 4, +          //      }, +          //    }, +          //  }, +        ], +      }, +      { +        test: /\.html$/, +        use: 'html-loader', +      }, +      { +        test: /\.(mp4|webm)$/, +        use: { +          loader: 'url-loader', +          options: { +            limit: 10000, +          }, +        }, +      }, +    ], +  }, +  node: { +    fs: 'empty' +  }, +  plugins: options.plugins.concat([ +    // Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV` +    // inside your code for any environment checks; Terser will automatically +    // drop any unreachable code. +    new HappyPack({ +      id: 'js', +      threadPool: happyThreadPool, +      loaders: ['babel-loader?cacheDirectory=true'] +    }), +    new webpack.DefinePlugin({ +      'process.env': { +        NODE_ENV: JSON.stringify(process.env.NODE_ENV), +      }, +    }), +    new webpack.ContextReplacementPlugin(/^\.\/locale$/, context => { +      if (!/\/moment\//.test(context.context)) { +        return; +      } +      // context needs to be modified in place +      Object.assign(context, { +      // include only CJK +        regExp: /^\.\/(ja|ko|zh)/, +        // point to the locale data folder relative to moment's src/lib/locale +        request: './locale' +      }); +    }) +  ]), +  resolve: { +    modules: ['node_modules', 'app'], +    extensions: ['.js', '.jsx', '.react.js'], +    mainFields: ['browser', 'jsnext:main', 'main'], +    alias: { +      'ba-components': path.resolve(__dirname, '../../app/components/'), +      'ba-containers': path.resolve(__dirname, '../../app/containers/'), +      'ba-actions': path.resolve(__dirname, '../../app/actions/'), +      'ba-styles': path.resolve(__dirname, '../../app/styles/components/'), +      'ba-helpers': path.resolve(__dirname, '../../app/styles/helpers/'), +      'ba-api': path.resolve(__dirname, '../../app/api/'), +      'ba-images': path.resolve(__dirname, '../../public/images/'), +      'ba-vendor': path.resolve(__dirname, '../../node_modules/'), +    } +  }, +  devtool: options.devtool, +  target: 'web', // Make web variables accessible to webpack, e.g. window +  performance: options.performance || {}, +}); diff --git a/front/odiparpack/internals/webpack/webpack.dev.babel.js b/front/odiparpack/internals/webpack/webpack.dev.babel.js new file mode 100644 index 0000000..dda13b8 --- /dev/null +++ b/front/odiparpack/internals/webpack/webpack.dev.babel.js @@ -0,0 +1,144 @@ +/** + * DEVELOPMENT WEBPACK CONFIGURATION + */ + +const path = require('path'); +const fs = require('fs'); +const glob = require('glob'); +const webpack = require('webpack'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin'); +const CircularDependencyPlugin = require('circular-dependency-plugin'); +const logger = require('../../server/logger'); +const pkg = require(path.resolve(process.cwd(), 'package.json')); // eslint-disable-line +const { dllPlugin } = pkg; + +const plugins = [ +  new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading +  new HtmlWebpackPlugin({ +    inject: true, // Inject all files that are generated by webpack, e.g. bundle.js +    template: 'app/index.html', +  }), +  new CircularDependencyPlugin({ +    exclude: /a\.js|node_modules/, // exclude node_modules +    failOnError: false, // show a warning when there is a circular dependency +  }), +]; + +if (dllPlugin) { +  glob.sync(`${dllPlugin.path}/*.dll.js`).forEach(dllPath => { +    plugins.push( +      new AddAssetHtmlPlugin({ +        filepath: dllPath, +        includeSourcemap: false, +      }), +    ); +  }); +} + +module.exports = require('./webpack.base.babel')({ +  mode: 'development', + +  // Add hot reloading in development +  entry: [ +    'eventsource-polyfill', // Necessary for hot reloading with IE +    'webpack-hot-middleware/client?reload=true', +    path.join(process.cwd(), 'app/app.js'), // Start with js/app.js +  ], + +  // Don't use hashes in dev mode for better performance +  output: { +    filename: '[name].js', +    chunkFilename: '[name].chunk.js', +  }, + +  optimization: { +    splitChunks: { +      chunks: 'all', +    }, +  }, + +  // Add development plugins +  plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define + +  // Emit a source map for easier debugging +  // See https://webpack.js.org/configuration/devtool/#devtool +  devtool: 'eval-source-map', + +  performance: { +    hints: false, +  }, +}); + +/** + * Select which plugins to use to optimize the bundle's handling of + * third party dependencies. + * + * If there is a dllPlugin key on the project's package.json, the + * Webpack DLL Plugin will be used. + * + */ +function dependencyHandlers() { +  // Don't do anything during the DLL Build step +  if (process.env.BUILDING_DLL) { +    return []; +  } + +  // Don't do anything if package.json does not have a dllPlugin property +  // Code splitting now included by default in Webpack 4 +  if (!dllPlugin) { +    return []; +  } + +  const dllPath = path.resolve( +    process.cwd(), +    dllPlugin.path || 'node_modules/react-boilerplate-dlls', +  ); + +  /** +   * If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json +   * Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude +   */ +  if (!dllPlugin.dlls) { +    const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json'); + +    if (!fs.existsSync(manifestPath)) { +      logger.error( +        'The DLL manifest is missing. Please run `npm run build:dll`', +      ); +      process.exit(0); +    } + +    return [ +      new webpack.DllReferencePlugin({ +        context: process.cwd(), +        manifest: require(manifestPath), // eslint-disable-line +      }), +    ]; +  } + +  // If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them. +  const dllManifests = Object.keys(dllPlugin.dlls) +    .map(name => path.join(dllPath, `/${name}.json`)); + +  return dllManifests.map(manifestPath => { +    if (!fs.existsSync(path)) { +      if (!fs.existsSync(manifestPath)) { +        logger.error( +          `The following Webpack DLL manifest is missing: ${path.basename( +            manifestPath, +          )}`, +        ); +        logger.error(`Expected to find it in ${dllPath}`); +        logger.error('Please run: npm run build:dll'); + +        process.exit(0); +      } +    } + +    return new webpack.DllReferencePlugin({ +      context: process.cwd(), +      manifest: require(manifestPath), // eslint-disable-line +    }); +  }); +} diff --git a/front/odiparpack/internals/webpack/webpack.dll.babel.js b/front/odiparpack/internals/webpack/webpack.dll.babel.js new file mode 100644 index 0000000..d1ee114 --- /dev/null +++ b/front/odiparpack/internals/webpack/webpack.dll.babel.js @@ -0,0 +1,58 @@ +/** + * WEBPACK DLL GENERATOR + * + * This profile is used to cache webpack's module + * contexts for external library and framework type + * dependencies which will usually not change often enough + * to warrant building them from scratch every time we use + * the webpack process. + */ + +const { join } = require('path'); +const defaults = require('lodash/defaultsDeep'); +const webpack = require('webpack'); +const pkg = require(join(process.cwd(), 'package.json')); // eslint-disable-line +const { dllPlugin } = require('../config'); + +if (!pkg.dllPlugin) { +  process.exit(0); +} + +const dllConfig = defaults(pkg.dllPlugin, dllPlugin.defaults); +const outputPath = join(process.cwd(), dllConfig.path); + +module.exports = require('./webpack.base.babel')({ +  mode: 'development', +  context: process.cwd(), +  entry: dllConfig.dlls ? dllConfig.dlls : dllPlugin.entry(pkg), +  optimization: { +    minimize: false, +  }, +  devtool: 'eval', +  output: { +    filename: '[name].dll.js', +    path: outputPath, +    library: '[name]', +  }, +  plugins: [ +    new webpack.DllPlugin({ +      name: '[name]', +      path: join(outputPath, '[name].json'), +    }), +    new webpack.ContextReplacementPlugin(/^\.\/locale$/, context => { +      if (!/\/moment\//.test(context.context)) { +        return; +      } +      // context needs to be modified in place +      Object.assign(context, { +      // include only CJK +        regExp: /^\.\/(ja|ko|zh)/, +        // point to the locale data folder relative to moment's src/lib/locale +        request: './locale' +      }); +    }) +  ], +  performance: { +    hints: false, +  }, +}); diff --git a/front/odiparpack/internals/webpack/webpack.prod.babel.js b/front/odiparpack/internals/webpack/webpack.prod.babel.js new file mode 100644 index 0000000..94ecac0 --- /dev/null +++ b/front/odiparpack/internals/webpack/webpack.prod.babel.js @@ -0,0 +1,154 @@ +// Important modules this config uses +const path = require('path'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const WebpackPwaManifest = require('webpack-pwa-manifest'); +const OfflinePlugin = require('offline-plugin'); +const { HashedModuleIdsPlugin } = require('webpack'); +const TerserPlugin = require('terser-webpack-plugin'); +const CompressionPlugin = require('compression-webpack-plugin'); + +module.exports = require('./webpack.base.babel')({ +  mode: 'production', + +  // In production, we skip all hot-reloading stuff +  entry: [ +    require.resolve('react-app-polyfill/ie11'), +    path.join(process.cwd(), 'app/app.js'), +  ], + +  // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets +  output: { +    filename: '[name].[chunkhash].js', +    chunkFilename: '[name].[chunkhash].chunk.js', +  }, + +  optimization: { +    minimize: true, +    minimizer: [ +      new TerserPlugin({ +        terserOptions: { +          warnings: false, +          compress: { +            comparisons: false, +          }, +          parse: {}, +          mangle: true, +          output: { +            comments: false, +            ascii_only: true, +          }, +        }, +        parallel: true, +        cache: true, +        sourceMap: true, +      }), +    ], +    nodeEnv: 'production', +    sideEffects: true, +    concatenateModules: true, +    splitChunks: { +      chunks: 'all', +      minSize: 30000, +      minChunks: 1, +      maxAsyncRequests: 5, +      maxInitialRequests: 3, +      name: true, +      cacheGroups: { +        commons: { +          test: /[\\/]node_modules[\\/]/, +          name: 'vendor', +          chunks: 'all', +        }, +        main: { +          chunks: 'all', +          minChunks: 2, +          reuseExistingChunk: true, +          enforce: true, +        }, +      }, +    }, +    runtimeChunk: true, +  }, + +  plugins: [ +    // Minify and optimize the index.html +    new HtmlWebpackPlugin({ +      template: 'app/index.html', +      minify: { +        removeComments: true, +        collapseWhitespace: true, +        removeRedundantAttributes: true, +        useShortDoctype: true, +        removeEmptyAttributes: true, +        removeStyleLinkTypeAttributes: true, +        keepClosingSlash: true, +        minifyJS: true, +        minifyCSS: true, +        minifyURLs: true, +      }, +      inject: true, +    }), + +    // Put it in the end to capture all the HtmlWebpackPlugin's +    // assets manipulations and do leak its manipulations to HtmlWebpackPlugin +    new OfflinePlugin({ +      relativePaths: false, +      publicPath: '/', +      appShell: '/', + +      // No need to cache .htaccess. See http://mxs.is/googmp, +      // this is applied before any match in `caches` section +      excludes: ['.htaccess'], + +      caches: { +        main: [':rest:'], + +        // All chunks marked as `additional`, loaded after main section +        // and do not prevent SW to install. Change to `optional` if +        // do not want them to be preloaded at all (cached only when first loaded) +        additional: ['*.chunk.js'], +      }, + +      // Removes warning for about `additional` section usage +      safeToUseOptionalCaches: true, +    }), + +    new CompressionPlugin({ +      algorithm: 'gzip', +      test: /\.js$|\.css$|\.html$/, +      threshold: 10240, +      minRatio: 0.8, +    }), + +    new WebpackPwaManifest({ +      name: 'React Boilerplate', +      short_name: 'React BP', +      description: 'My React Boilerplate-based project!', +      background_color: '#fafafa', +      theme_color: '#b1624d', +      inject: true, +      ios: true, +      cons: [ +        { +          src: path.resolve('public/images/logo.png'), +          sizes: [72, 96, 128, 144, 192, 384, 512], +        }, +        { +          src: path.resolve('public/images/logo.png'), +          sizes: [120, 152, 167, 180], +          ios: true, +        }, +      ], +    }), + +    new HashedModuleIdsPlugin({ +      hashFunction: 'sha256', +      hashDigest: 'hex', +      hashDigestLength: 20, +    }), +  ], + +  performance: { +    assetFilter: assetFilename => !/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename), +  }, +}); | 
