Tuesday, November 28, 2023

React 18 Webpack 5 New Jest Testing with Server Side Rendering

  We are using Webpack 5.89 and related package.  


https://github.com/harshal1982/react18-ssr


    Basic Project Structure





Package.json

{
  "name": "harshal-ssr",
  "version": "2.0.1",
  "description": "Server side rendering project",
  "main": "index.js",
  "scripts": {
    "clean:build": "rimraf build public",
    "dev": "npm run clean:build && webpack --mode development --watch",
    "test": "jest --coverage -u"
  },
 
  "author": "",
  "license": "ISC",
  "jest": {
    "transform": {
      "^.+\\.(js|ts)$": "babel-jest"
    },
    "transformIgnorePatterns": [],
    "testEnvironment": "jsdom",
    "moduleNameMapper": {
      "\\.(css|less|scss)$": "<rootDir>/tests/css/__mocks__/styleMock.js"
    }
  },
  "dependencies": {
    "@babel/polyfill": "^7.12.1",
    "@babel/preset-typescript": "^7.23.2",
    "@babel/register": "^7.22.15",
    "@reduxjs/toolkit": "^1.9.7",
    "async_hooks": "^1.0.0",
    "axios": "^1.6.0",
    "babel-loader": "^9.1.3",
    "compression": "^1.7.4",
    "concurrently": "^8.2.2",
    "copy-webpack-plugin": "^11.0.0",
    "express": "^4.18.2",
    "express-http-proxy": "^2.0.0",
    "fs": "^0.0.1-security",
    "lodash": "^4.17.21",
    "net": "^1.0.2",
    "nodemon": "^3.0.1",
    "nodemon-webpack-plugin": "^4.8.2",
    "npm-run-all": "^4.1.5",
    "path": "^0.12.7",
    "progress-bar-webpack-plugin": "^2.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-helmet": "^6.1.0",
    "react-redux": "^8.1.3",
    "react-router-config": "^5.1.1",
    "react-router-dom": "^6.18.0",
    "redux": "^4.2.1",
    "redux-thunk": "^2.4.2",
    "rimraf": "^5.0.5",
    "serialize-javascript": "^6.0.1",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1",
    "webpack-merge": "^5.10.0",
    "webpack-node-externals": "^3.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.23.2",
    "@babel/plugin-proposal-class-properties": "^7.18.6",
    "@babel/plugin-transform-runtime": "^7.23.2",
    "@babel/preset-env": "^7.23.3",
    "@babel/preset-react": "^7.23.3",
    "@testing-library/jest-dom": "^6.1.4",
    "@testing-library/react": "^14.1.2",
    "@testing-library/react-hooks": "^8.0.1",
    "babel-jest": "^29.7.0",
    "css-loader": "^6.8.1",
    "html-webpack-plugin": "^5.5.3",
    "jest": "^29.7.0",
    "jest-environment-jsdom": "^29.7.0",
    "mini-css-extract-plugin": "^2.7.6",
    "node-polyfill-webpack-plugin": "^2.0.1",
    "nyc": "^15.1.0",
    "react-test-renderer": "^18.2.0",
    "redux-mock-store": "^1.5.4",
    "sass": "^1.69.5",
    "sass-loader": "^13.3.2",
    "style-loader": "^3.3.3",
    "webpack-manifest-plugin": "^5.0.0"
  }
}



webpack.config.js

module.exports = require(`./config/webpack.${process.env.NODE_ENV || 'development'}.js`);



.babelrc


{
    "presets": ["@babel/preset-env", "@babel/preset-react"],
    "plugins": [ "@babel/plugin-transform-runtime","@babel/plugin-proposal-class-properties"]
}


config/webpack.client.common.js


const MiniCssExtractPlugin = require('mini-css-extract-plugin');


const config = {
  module: {
    rules: [
      {
        test: /\.?js|jsx$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
          },
        },
      },
      {
        test: /\.(svg|jpg|jpeg|png|gif|pdf)$/,
        exclude: /fonts/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: './images/[name].[ext]',
              publicPath: '/',
            },
          },
        ],
      },
      {
        test: /\.(scss|css)$/,
        exclude: /node_modules/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
      },
    ],
  },
};

module.exports = config;

config/webpack.development.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const WebpackManifestPlugin = require('webpack-manifest-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const NodemonPlugin = require('nodemon-webpack-plugin');
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const clientcommonconfig = require('./webpack.client.common');
const servercommonconfig = require('./webpack.server.common')
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const clientConfig = merge(clientcommonconfig, {
  mode: 'development',
  target: 'web',
  entry: './src/app/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../public'),
   
  },

 
  plugins: [
    new ProgressBarPlugin(),
    new CopyWebpackPlugin({
        patterns: [
          {from: "src/images", to: "images/"}
        ],
      }),
    new webpack.DefinePlugin({
      HTTP_DEFAULT_TIMEOUT: 5000,
    }),
  ],
});

const serverConfig =  merge(servercommonconfig, {
  mode: 'development',
  target: 'node',
  entry: './src/server/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../build'),
   
  },
  externals: [nodeExternals()],  
  plugins: [
    new ProgressBarPlugin(),
   
    new NodePolyfillPlugin(),
    new NodemonPlugin({
      watch: path.resolve('../build'),
      ext: 'js,json',
      filename: 'server.js',
      verbose: true,
      env: {
        NODE_ENV: 'development',
      },
    }),
    new webpack.DefinePlugin({
      HTTP_DEFAULT_TIMEOUT: 5000,
    }),
  ],
});

module.exports = [clientConfig, serverConfig];


config/webpack.server.common.js


const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const config = {
  module: {
    rules: [
      {
        test: /\.?js|jsx$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react'],
          },
        },
      },
      {
        test:/\.(scss|css)$/,
        exclude: /node_modules/,
        use: ['style-loader','css-loader', 'sass-loader'],
      },
    ],
  },
};

module.exports = config;

Labels:

0 Comments:

Post a Comment

Subscribe to Post Comments [Atom]

<< Home