Skip to content

Instantly share code, notes, and snippets.

@xfsnowind
Created December 27, 2023 08:06
Show Gist options
  • Save xfsnowind/a412a5b4434a821c3d3237252208e702 to your computer and use it in GitHub Desktop.
Save xfsnowind/a412a5b4434a821c3d3237252208e702 to your computer and use it in GitHub Desktop.
rspack config file
require('dotenv').config()
const { join } = require('path')
const rspack = require('@rspack/core')
const { defineConfig } = require('@rspack/cli')
const ReactRefreshPlugin = require('@rspack/plugin-react-refresh')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const {
resolveJSAndTS,
getModuleJSAndTSRules,
plugins: { ignoreMomentLocalesPlugin },
} = require('./webpack.config.base')
const packageConfig = require('../../package.json')
const { version } = packageConfig
const ENVS = {
DEV: 'development',
PROD: 'production',
CYPRESS_COMPONENT_TEST: 'cypress-component-test',
}
const nodeEnv = process.env.NODE_ENV
if (!Object.values(ENVS).includes(nodeEnv)) {
throw new Error(`Invalid NODE_ENV: ${nodeEnv}`)
}
const isCypressEnv = process.env.CYPRESS === 'true'
const useReactRefresh = nodeEnv === ENVS.DEV && !isCypressEnv
const mode = nodeEnv === ENVS.DEV ? 'development' : 'production'
module.exports = defineConfig({
target: ['browserslist'],
mode,
entry: './src/index.tsx',
stats: 'normal',
output: {
...(nodeEnv === ENVS.PROD && {
path: join(process.cwd(), 'dist/apps/fleet-web'),
filename: 'static/js/[name].[contenthash].js',
chunkFilename: 'static/js/[name].[contenthash].chunk.js',
// Css
cssFilename: 'static/css/[name].[contenthash].css',
cssChunkFilename: 'static/css/[name].[contenthash].chunk.css',
}),
module: true,
publicPath: '/',
},
optimization: {
splitChunks: false,
// splitChunks: {
// // Last tested with "@rspack/core": "0.2.12"
// // If we don't do this, rspack will create two (compressed) 4.8MB chunks (one for vendor and one for main). That's just not good!
// // Chunks: 'initial' produces one main 4.7MB chunk and other small ones (just like webpack)
// // We should try to remove this once rspack provides a better default
// chunks: nodeEnv === ENVS.PROD ? 'initial' : undefined,
// },
},
context: __dirname,
devtool: (() => {
if (nodeEnv === ENVS.CYPRESS_COMPONENT_TEST) {
return 'eval' // for performance reasons
}
return nodeEnv === ENVS.DEV
? 'eval-cheap-module-source-map'
: 'nosources-source-map'
})(),
devServer:
nodeEnv === ENVS.DEV
? {
historyApiFallback: true,
host: '0.0.0.0',
port: 8080,
hot: true,
liveReload: false,
static: __dirname,
devMiddleware: { publicPath: '/' },
client: { overlay: false },
}
: undefined,
resolve: resolveJSAndTS,
module: {
rules: [
...getModuleJSAndTSRules({ useReactRefresh }),
{
test: /\.scss$/,
exclude: /node_modules/,
use: ['postcss-loader', 'sass-loader'],
type: 'css',
},
{
test: /\.css$/,
type: 'css',
},
{
test: /\.pdf$/,
type: 'asset/resource',
generator: {
filename: 'assets/[name][ext]',
},
},
{
test: /\.svg$/,
exclude: /assets/,
type: 'asset/inline',
},
{
test: /\.svg$/,
include: /assets/,
/** Deprecated plugin - Convert to imaginin svgo with "removeDimensions: true" */
use: [
{
loader: 'svg-inline-loader',
options: {
removeTags: true,
removingTags: ['title'],
},
},
],
},
{
test: /\.(jpe?g|png|gif|ico|eot|woff|otf|ttf|woff2|webp)$/,
type: 'asset',
},
{
test: /\.(mp3)(\?.*)?$/,
type: 'asset/inline',
},
],
},
plugins: [
ignoreMomentLocalesPlugin,
nodeEnv === ENVS.DEV &&
new ForkTsCheckerWebpackPlugin({
typescript: {
configFile: 'tsconfig.app.json',
memoryLimit: 5900,
/** Recommended mode when used with babel loader
* Check https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/blob/master/README.md#typescript-options
*/
mode: 'write-references',
diagnosticOptions: {
/* Since babel only transpiles typescript, this plugin has to cover all types of errors (both semantic and syntactic). */
syntactic: true,
},
},
}),
// cypress-rspack-dev-server already applies this plugin so we don't do it again to prevent conflicts
new rspack.HtmlRspackPlugin({ template: './index.ejs' }),
new rspack.ProvidePlugin({ process: 'process', Buffer: ['buffer', 'Buffer'] }),
new rspack.CopyRspackPlugin({
patterns: [
{
from: 'assets/customer_styling/*',
to: 'assets/[name][ext]',
},
{
from: 'assets/img/*',
to: 'assets/[name][ext]',
},
{
from: 'assets/templates/*',
to: 'assets/[name][ext]',
},
{
from: 'assets/icons/favicons/*',
to: 'assets/[name][ext]',
},
{
from: 'assets/templates-delivery/**/*',
},
],
}),
new rspack.DefinePlugin({
ENV: {
...(nodeEnv === ENVS.PROD
? {
NODE_ENV: 'production',
GA_TRACKING_ID: 'UA-153974304-1',
GMAP_API_KEY: process.env.STAGING
? process.env.STAGING_GMAP_API_KEY
: process.env.GMAP_API_KEY,
SENTRY_DSN:
'https://704d2e66ddc9464faf0549f0d139cc08@o94568.ingest.sentry.io/1444444',
}
: {
NODE_ENV: 'development',
WITH_ELD: process.env.WITH_ELD,
ENABLE_REDUX_DEV_MIDDLEWARE: process.env.ENABLE_REDUX_DEV_MIDDLEWARE,
WITH_COMMUNICATOR: process.env.WITH_COMMUNICATOR,
DEVELOPMENT_ENDPOINT:
process.env.DEVELOPMENT_ENDPOINT ||
`https://fleetweb${process.env.TEST_ENV || 'dev'}-${
process.env.DEVELOPMENT_COUNTRY
}.cartrack.com/jsonrpc/index.php`,
GMAP_API_KEY: process.env.GMAP_API_KEY,
}),
DEPLOYMENT_ENV: process.env.DEPLOYMENT_ENV || 'unspecified',
APP_VERSION: version,
HERE_MAPS_API_KEY: process.env.HERE_MAPS_API_KEY,
CYPRESS_CT_ENV: nodeEnv === ENVS.CYPRESS_COMPONENT_TEST,
/* EXPERIMENTAL FEATURES */
FEAT_MIFLEET_DECIMAL_SEPARATORS: process.env.FEAT_MIFLEET_DECIMAL_SEPARATORS,
NEW_LOGIN: process.env.NEW_LOGIN,
NEW_GEOFENCE: process.env.NEW_GEOFENCE === 'true',
NEW_REPORTS: process.env.NEW_REPORTS === 'true',
FLAG_NEW_REDESIGN: process.env.FLAG_NEW_REDESIGN === 'true',
},
}),
useReactRefresh && new ReactRefreshPlugin(),
].filter(Boolean),
experiments: {
rspackFuture: {
disableTransformByDefault: true,
},
},
})
@xfsnowind
Copy link
Author

webpack.config.base.ts file:

const webpack = require('webpack')
const { join, resolve } = require('path')

module.exports = {
  // Contains isolated configs so they can be used more freely
  plugins: {
    // https://webpack.js.org/plugins/ignore-plugin/#example-of-ignoring-moment-locales
    ignoreMomentLocalesPlugin: new webpack.IgnorePlugin({
      resourceRegExp: /^\.\/locale$/,
      contextRegExp: /moment$/,
    }),
  },
  resolveJSAndTS: {
    extensions: ['.js', '.jsx', '.ts', '.tsx'],
    fallback: {
      buffer: require.resolve('buffer'),
    },
    alias: {
      /** Webpack v5 does not bundle Nodejs core lib anymore hence we need to polyfill the modules we use.
       *  Please, REMOVE if we don't use them anymore (builds should succeed) */
      fs: 'browserify-fs',
      vm: 'vm-browserify',
      stream: 'stream-browserify',
      crypto: 'crypto-browserify',
      zlib: 'browserify-zlib',
      worker_threads: false,
      /** ------------------------ */
      // This is a temporary solution. Ideally we should not have to specify aliases both here and in tsconfig
      'cartrack-ui-kit': join(__dirname, 'src/util-components'),
      'cartrack-utils': join(__dirname, 'src/util-functions'),
      'cartrack-moment-utils': join(__dirname, 'src/util-functions/moment-helper.ts'),
      assets: join(__dirname, 'assets/'),
      api: join(__dirname, 'src/api/'),
      duxs: join(__dirname, 'src/duxs/'),
      forms: join(__dirname, 'src/modules/forms/'),
      tables: join(__dirname, 'src/modules/tables/'),
      src: join(__dirname, 'src/'),
      '@karoo-ui/core-rhf': join(__dirname, 'src/shared/react-hook-form/index.ts'),
      '@karoo-ui/core': resolve(__dirname, '../../dist/libs/karoo-ui/core/index.js'),
      '@karoo-ui/icons': resolve(__dirname, '../../dist/libs/karoo-ui/icons'),
      '@karoo-ui/system': resolve(__dirname, '../../dist/libs/karoo-ui/system'),
      '@karoo/utils': resolve(__dirname, '../../dist/libs/karoo-utils/index.mjs'),
    },
  },
  getModuleJSAndTSRules: ({ useReactRefresh }) => {
    if (typeof useReactRefresh !== 'boolean') {
      throw new Error('[getModuleJSAndTSRules] - Please provide valid parameters')
    }

    return [
      {
        test: /\.(j|t)s(x)?$/,
        include: resolve(__dirname, 'src'),
        loader: 'builtin:swc-loader',
        options: {
          // In case we need to use babel-loader again (hopefully not) we should use this flag
          // parseMap: true, // See https://swc.rs/docs/usage/swc-loader#with-babel-loader
          sourceMap: true,
          env: {
            targets: 'defaults and supports es6-module',
          },
          jsc: {
            parser: {
              syntax: 'typescript',
              tsx: true,
              dynamicImport: true,
            },
            transform: {
              react: {
                runtime: 'automatic',
                refresh: useReactRefresh,
                development: useReactRefresh,
              },
            },
          },
        },
      },
    ]
  },
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment