Using Webpack to build react library

.babelrc
{
    // compile to browser-compatible language based on browserlist supported 
    "presets": ["@babel/preset-env", "@babel/preset-react"],
    "plugins": [
        "@babel/plugin-syntax-dynamic-import",
        "react-hot-loader/babel"
    ]
}
index.tsx
export {default as Button} from "./Button";
tsconfig.json
{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "jsx": "react-jsx",
    "baseUrl": "src",
    // Generate type file
    "declaration": true,
    "declarationDir": "dist",
  },
  "include": [
    "**/*.ts",
    "**/*.tsx"
  ]
}
webpack.config.js
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const nodeExternals = require('webpack-node-externals');
const path = require("path");
module.exports = {
    entry:{
        main: "./src/index.tsx",
    },
    mode: "production",
    // prevent bundling with node_modules
    externals: [nodeExternals()],
    output:{
        filename:'index.js',
        path: __dirname + "/dist",
        library: 'my_webpack_library',
        // support import from other application with multiple syntaxs
        libraryTarget: 'umd',
    },
    resolve:{
        alias: {
        },
        extensions:[".ts",".tsx",".js",".scss",".css"],
        modules: [ "node_modules"]
    },
    plugins:[
      // clear the previous for each build
      new CleanWebpackPlugin(),
    ],
    module:{
        rules:[
          {
            test: /\.tsx?$/,
            use: ["babel-loader" , {
              loader: "ts-loader",
              options: {
                configFile: "tsconfig.json",
              },
            }],
            exclude: /node_modules/,
          },
          {
            test: /\.scss$/i,
            use: [
              "style-loader",  
              {
                loader: "css-loader",
                options: {
                  modules: true,
                },
              },
              "sass-loader"
            ],
          }
        ]
    },
}
package.json
{
  "name": "my_webpack_library",
  "version": "1.1.0",
  "license": "MIT",
  "main": "dist/index.js",
  "files": [
    "dist"
  ],
  "scripts": {
    "build": "webpack --config webpack.config.js --mode production",
    "start": "webpack serve --config webpack.dev.config.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/headshootcheng/webpack-library.git"
  },
  "dependencies": {
   
  },
  "devDependencies": {
    "@hot-loader/react-dom": "^17.0.2",
    "react-hot-loader": "^4.13.0",
    "@babel/core": "^7.18.6",
    "@babel/plugin-proposal-class-properties": "^7.18.6",
    "@babel/plugin-syntax-dynamic-import": "^7.8.3",
    "@babel/preset-env": "^7.18.6",
    "@babel/preset-react": "^7.18.6",
    "@types/react": "^18.0.14",
    "@types/react-dom": "^18.0.5",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.6.0",
    "html-webpack-plugin": "^5.5.0",
    "mini-css-extract-plugin": "^2.5.3",
    "sass-loader": "^12.6.0",
    "style-loader": "^3.3.1",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.5",
    "typescript-plugin-css-modules": "^3.4.0",
    "webpack": "^5.69.1",
    "webpack-cli": "^4.9.2",
    "webpack-dev-server": "^4.9.3",
    "webpack-node-externals": "^3.0.0",
    "babel-loader": "^8.2.5",
    "node-sass": "^7.0.1",
    "prop-types": "^15.8.1",
    "sass": "^1.49.9",
    "@emotion/react": "^11.9.3",
    "@emotion/styled": "^11.9.3",
    "@mui/material": "^5.8.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.3.0"
  },
  // consume consumer node_modules to prevent duplication of library
   "peerDependencies": {
    "@emotion/react": "^11.9.3",
    "@emotion/styled": "^11.9.3",
    "@mui/material": "^5.8.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.3.0"
  }
}
main.yml
# The pipeline for publish npm package

name: Publish Package to npmjs

# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the "main" branch
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      # Setup .npmrc file to publish to npm
      - uses: actions/setup-node@v3
        with:
          node-version: '16.x'
          registry-url: 'https://registry.npmjs.org'
          # Defaults to the user or organization that owns the workflow file
          scope: '@octocat'
      - run: yarn
      - run: yarn build
      - run: yarn publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

Last updated

Was this helpful?