How can you speed up webpack compilation (or separate it from server restart)

Issue

I currently have this setup:

import path from 'path'

import type {Configuration} from 'webpack'

const config: Configuration = {
  mode: 'development',
  entry: path.join(__dirname, '../..', 'dev/client.ts'),
  output: {
    path: path.join(__dirname, '../..', 'public'),
    filename: 'script.js',
    assetModuleFilename: '[name][ext]',
    publicPath: '/',
    libraryTarget: 'umd',
    clean: false,
  },
  target: 'web',
  resolve: {
    extensions: ['.js', '.ts', '.jsx', '.tsx'],
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.(c|sc|sa)ss$/,
        use: ['style-loader', 'css-loader', 'sass-loader'],
        exclude: /node_modules/,
      },
      {
        test: /\.(ico|svg|png|jpg)$/,
        type: 'asset/resource',
      },
    ],
  },
  stats: 'errors-warnings',
  performance: {
    hints: false,
    maxAssetSize: 400000,
    maxEntrypointSize: 400000,
  },
  devtool: 'source-map',
  watch: true,
  watchOptions: {
    aggregateTimeout: 100,
    poll: 1000,
    followSymlinks: true,
    ignored: /node_modules/,
  },
}

export default config

Then I invoke the compiler with:

webpack(configuration, (error, stats) => {
  if (error) {
    console.log(error)
  }

  if (stats && stats.hasErrors()) {
    console.log(stats.toJson().errors)
  }

  if (stats) {
    console.log('Compiled in: ' + stats.toJson().time)
  }
})

Which results in Compiled in: 4701 whenever you initially start up the server, after that whenever you make any file changes it’ll be ~200ms to recompile it after webpack is already watching files, so it’s only on the initial build.

Incremental builds is also already enabled.

Is there any way or any configuration I can do to decrease the compile time of the initial server startup? I want to run it along with ts-node-dev and my socket is refreshing the browser in ~100ms, so I don’t want to wait 4 seconds on every server file change before I can see anything in browser but I also want to be able to run the client bundle and server using the same script and console, so the problem is every time you make any server file change it completely recompiles the client.

Currently I have tsnd --transpile-only src/dev/server.ts as my dev script. That index is building both the client and the server, which is what I want, however using tsnd on that file will cause the entire file to rebuild on server file changes and implicitly also rebuild the entire client (which isn’t what I want). Is there another way I can set this up so that I can still run both using the same script but without rebuilding the entire client on server changes. I know that I can use nodemon and run them as separate processes but that sort of defeats the point of using ts-node-dev, is there an alternative option or something stupid that I’m not thinking about?

I’d also like to know if there’s a way to disable type checking for ts-loader only during development mode in webpack, which is something that’ll further speed it up. Well anything I can use to optimize it I’d really appreciate.

Solution

After more trial and error I finally found a solution using spawn.

import {spawn} from 'child_process'

const bundle = spawn('npm', ['run', 'bundle'])

bundle.stdout.on('data', (data) => {
  console.log(data.toString('utf-8'))
})

bundle.stderr.on('data', (data) => {
  console.error(data.toString('utf-8'))
})

bundle.on('close', (code) => {
  console.log(code)
})

const server = spawn('npm', ['run', 'serve'])

server.stdout.on('data', (data) => {
  console.log(data.toString('utf-8'))
})

server.stderr.on('data', (data) => {
  console.error(data.toString('utf-8'))
})

server.on('close', (code) => {
  console.log(code)
})

Along with:

  "bundle": "node lib/dev/bundle.js",
  "serve": "tsnd --transpile-only src/dev/server.ts",
  "dev": "node lib/dev/index.js",`

This will allow you to separate your client bundle into one file, your tsnd server in another file, and to call both of them as child processes of the primary index. Now the server recompiles only on server file changes and the client recompiles only on client file changes and it’s incredibly fast.

Though I don’t know the caveats with doing it this way (it’s the first time I’m spawning children like this), so I guess I’ll figure out soon if there’s any downside or issues with doing this. For now though everything everywhere recompiles and restarts under ~200ms.

Answered By – Matriarx

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published