UNPKG

@25sprout/react-starter

Version:

25sprout web starter with React

212 lines (209 loc) 4.86 kB
import path from 'path'; import webpack from 'webpack'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import TerserPlugin from 'terser-webpack-plugin'; import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin'; import media from './config/media'; import env from './config/env'; import endpoint from './config/endpoint'; export default { devtool: 'eval-cheap-module-source-map', mode: 'development', entry: { app: ['webpack-hot-middleware/client', './src/index.tsx'], }, output: { path: path.join(__dirname, 'public'), filename: '[name].bundle.js', publicPath: '/', }, plugins: [ new webpack.HotModuleReplacementPlugin(), new ReactRefreshWebpackPlugin(), new webpack.DefinePlugin({ 'process.env': { ...env, ...endpoint }, }), new HtmlWebpackPlugin({ template: './src/index.html', chunksSortMode: 'auto', }), ], optimization: { minimizer: [ new TerserPlugin({ terserOptions: { ecma: 5, compress: { warnings: false, comparisons: false, }, output: { comments: false, ascii_only: false, }, }, }), ], // Automatically split vendor and commons // https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758 splitChunks: { chunks: 'all', maxInitialRequests: Infinity, minSize: 0, cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: 'commons', chunks: 'all', }, }, }, runtimeChunk: 'single', }, module: { rules: [ { test: /\.tsx?$/, include: path.join(__dirname, 'src'), exclude: path.join(__dirname, 'node_modules'), loader: 'babel-loader', options: { presets: [ ['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3 }], '@babel/preset-react', '@babel/preset-typescript', ], plugins: [ 'react-refresh/babel', [ 'module-resolver', { root: ['./src'], alias: { components: './src/components', images: './src/images', layouts: './src/layouts', models: './src/models', routes: './src/routes', store: './src/store', util: './src/util', }, }, ], '@babel/plugin-syntax-dynamic-import', '@babel/plugin-syntax-import-meta', '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-json-strings', '@babel/plugin-transform-react-constant-elements', ], babelrc: false, }, }, { test: /\.css$/, include: [path.join(__dirname, 'src'), path.join(__dirname, 'config')], use: [ 'style-loader', { loader: 'css-loader', options: { modules: { exportLocalsConvention: 'camelCase', localIdentName: '[name]__[local]___[hash:base64:5]', }, importLoaders: 1, sourceMap: true, }, }, { loader: 'postcss-loader', options: { sourceMap: true, postcssOptions: { plugins: [ 'postcss-import', [ 'postcss-preset-env', { stage: 0, importFrom: [ './config/palette.css', { customMedia: media, }, ], preserve: false, features: { 'custom-properties': { disableDeprecationNotice: true, }, }, }, ], ], }, }, }, ], }, { test: /\.css$/, include: path.join(__dirname, 'node_modules'), use: ['style-loader', { loader: 'css-loader', options: { sourceMap: true } }], }, { test: /\.(jpe?g|png|gif)$/, include: path.join(__dirname, 'src'), loader: 'url-loader', options: { limit: 10000, name: './assets/[name]__[contenthash].[ext]', }, }, { test: /^(?!.*\.inline\.svg$).*\.svg$/, include: path.join(__dirname, 'src'), use: [ '@svgr/webpack', { loader: 'url-loader', options: { limit: 10000, name: './assets/[name]__[contenthash].[ext]', }, }, ], }, // Weboack 5 new config for asset // { // test: /\.(svg|ico|jpg|jpeg|png|apng|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/, // type: 'asset/resource', // generator: { filename: 'static/media/[path][name][ext]' } // } { test: /\.inline.svg$/, include: path.join(__dirname, 'src'), loader: '@svgr/webpack', options: { svgoConfig: { plugins: [ { name: 'preset-default', params: { overrides: { cleanupIDs: false, removeViewBox: false, }, }, }, ], }, }, }, ], }, resolve: { modules: ['node_modules'], extensions: ['.ts', '.tsx', '.js'], }, };