mmiller42 / html-webpack-externals-plugin

Webpack plugin that works alongside html-webpack-plugin to use pre-packaged vendor bundles.
MIT License
99 stars 16 forks source link

How to use with Typescript? #44

Open samism opened 5 years ago

samism commented 5 years ago

Hi,

I'm trying to incorporate this into my production build. I am externalizing React and React-DOM from my local node_modules. When I go to see index.html in the browser, I get require() is not defined, React is not defined, etc.

AFAI understand, externalizing these libs means that in my code, I don't have to import them, since the libraries will be included in <script> tags in my index.html. Now, I want to be able to develop as usual. In my React files, I am importing React, ReactDom, and tons of other things. When I go to build, TypeScript says that I need to import, or Webpack won't go through with the build. I tried setting module: none in my tsconfig, but that means I won't be able to import anything ever.

How can I get this to work?

webpack.config.prod.js

const path = require('path');
const nodeExternals = require('webpack-node-externals');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');

const externals = [
  {
    module: 'react',
    entry: 'cjs/react.production.min.js',
    global: 'React',
  },
  {
    module: 'react-dom',
    entry: 'cjs/react-dom.production.min.js',
    global: 'ReactDOM',
  },
];

module.exports = [
  {
    mode: 'production',
    entry: path.resolve(__dirname, 'src/app.ts'),
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist'),
    },
    module: {
      rules: [
        {
          test: /\.ts?$/,
          loader: 'ts-loader',
          exclude: /node_modules/,
          options: {
            configFile: path.resolve(__dirname, 'tsconfig.json'),
          },
        },
      ],
    },
    resolve: {
      extensions: ['.ts', '.js'],
    },
    target: 'node',
    externals: [nodeExternals()],
  },
  {
    mode: 'production',
    entry: path.resolve(__dirname, 'src/client/index.tsx'),
    output: {
      filename: '[name].[contentHash].bundle.js',
      path: path.resolve(__dirname, 'dist/public'),
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          loader: 'ts-loader',
          exclude: /node_modules/,
          options: {
            configFile: path.resolve(__dirname, 'src/client/tsconfig.json'),
          },
        },
        {
          test: /\.css$/,
          use: ['css-loader'],
        },
      ],
    },
    resolve: {
      extensions: ['.tsx', '.ts', '.js', '.css'],
    },
    target: 'web',
    optimization: {
      minimizer: [new OptimizeCssAssetsPlugin(), new TerserPlugin()],
    },
    plugins: [
      new MiniCssExtractPlugin({ filename: '[name].[contentHash].css' }),
      new CleanWebpackPlugin(),
      new HtmlWebpackPlugin({
        template: path.resolve(__dirname, 'src/client/public/index.html'),
        // minify: {
        //   removeAttributeQuotes: true,
        //   collapseWhitespace: true,
        //   removeComments: true,
        // },
      }),
      new HtmlWebpackExternalsPlugin({ externals, hash: true }),
    ],
  },
];