xcv58/Custom-JavaScript-for-Websites-2

View on GitHub
webpack.config.js

Summary

Maintainability
A
0 mins
Test Coverage
const webpack = require('webpack')
const path = require('path')
const fileSystem = require('fs')
const env = require('./utils/env')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ProgressBarPlugin = require('progress-bar-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

const srcPath = (subdir) => {
  return path.join(__dirname, 'src/js', subdir)
}

const alias = {
  background: srcPath('background'),
  components: srcPath('components'),
  libs: srcPath('libs'),
  stores: srcPath('stores'),
  svgIcons: srcPath('svgIcons'),
  img: path.join(__dirname, 'src/img')
}

const secretsPath = path.join(__dirname, 'secrets.' + env.NODE_ENV + '.js')

const fileExtensions = [
  'jpg',
  'jpeg',
  'png',
  'gif',
  'eot',
  'otf',
  'svg',
  'ttf',
  'woff',
  'woff2'
]

if (fileSystem.existsSync(secretsPath)) {
  alias.secrets = secretsPath
}

const imgDir = path.join(__dirname, 'src/img')
const images = fileSystem
  .readdirSync(imgDir)
  .filter((x) => x.endsWith('.png'))
  .map((x) => path.join(imgDir, x))

const HtmlFiles = ['popup'].map(
  (name) =>
    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src', `${name}.html`),
      filename: `${name}.html`,
      chunks: [name],
      minify: {
        collapseWhitespace: true
      }
    })
)

const entry = Object.assign(
  ...['popup', 'background', 'run', 'base'].map((name) => ({
    [name]: path.join(__dirname, 'src', 'js', `${name}.tsx`)
  }))
)

const options = {
  entry,
  output: {
    path: path.join(__dirname, 'build'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.m?js/,
        type: 'javascript/auto',
        resolve: {
          fullySpecified: false
        }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: new RegExp(`\\.(${fileExtensions.join('|')})$`),
        loader: 'file-loader',
        options: {
          name: '[name].[ext]'
        },
        include: path.resolve(__dirname, 'src'),
        exclude: /node_modules/
      },
      {
        test: /\.html$/,
        loader: 'html-loader',
        include: path.resolve(__dirname, 'src'),
        exclude: /node_modules/
      },
      {
        test: /\.(js|ts)x?$/,
        use: [
          {
            loader: 'ts-loader',
            options: {
              transpileOnly: true,
              experimentalWatchApi: true
            }
          }
        ],
        include: path.resolve(__dirname, 'src')
      }
    ]
  },
  resolve: {
    alias,
    extensions: fileExtensions
      .map((extension) => '.' + extension)
      .concat(['.css', '.jsx', '.js', '.tsx', 'ts'])
  },
  plugins: [
    // expose and write the allowed env vars on the compiled bundle
    new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css'
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(env.NODE_ENV)
    }),
    new CopyWebpackPlugin({
      patterns: [
        ...images,
        {
          from: 'src/manifest.json',
          transform: function (content, path) {
            return Buffer.from(
              JSON.stringify({
                description: process.env.npm_package_description,
                version: process.env.npm_package_version,
                ...JSON.parse(content.toString())
              })
            )
          }
        }
      ]
    }),
    ...HtmlFiles,
    new ProgressBarPlugin()
  ]
}

if (env.NODE_ENV === 'development') {
  options.devtool = 'eval-cheap-source-map'
}

module.exports = (plugins = []) => ({
  ...options,
  plugins: [...options.plugins, ...plugins]
})