代码之家  ›  专栏  ›  技术社区  ›  blits

使HMR与ESM和Node协同工作。JS和Webpack API

  •  0
  • blits  · 技术社区  · 3 年前

    当然,我看过很多 examples 这将阐明如何使其与webpack CLI一起工作。

    但我正在努力了解如何在通过API直接使用webpack捆绑器时使其工作,我无法找到任何适合我的方法。我尝试这样做:

    const compiler = webpack(await createWebpackConfig(entry))
    
      if (runDevServer) {
        compiler.watch(
          {
            aggregateTimeout: 1000,
          },
          (err, stats) => {
            process.stdout.write(`${stats.toString({ colors: true })}\n\n`)
          }
        )
    

    通过拥有 ['webpack/hot/poll?100', entry] 在条目中。

    但这不起作用,因为我必须以某种方式运行我的HMR服务器,否则应用程序将无法接收任何更新,我的应用程序实例中出现以下错误。

    [HMR] Update failed: TypeError: fetch failed
        at Object.fetch (node:internal/deps/undici/undici:11457:11)
    

    我的webpack配置如下:

    const isProduction = process.env.NODE_ENV === 'production'
    const runDevServer = !!process.env.RUN_DEV_SERVER
    
    export async function createWebpackConfig(entry: string): Promise<Configuration> {
      const packages = await findMonorepoPackages()
    
      const workspaces = packages.map(name => new RegExp(`^${name}(/.*)?$`))
      const allowedPackages = [...workspaces, /webpack\/hot\/poll\?100/]
    
      if (isProduction) {
        console.log('Making production build')
      }
    
      if (runDevServer) {
        console.log(`Going to run dev server of ${path.basename(entry, '.ts')}.mjs`)
      }
      const baseConfig: Configuration = {
        context: process.cwd(),
        watch: runDevServer,
        mode: isProduction ? 'production' : 'development',
        node: {
          __dirname: false,
          __filename: false,
        },
        devtool: 'source-map',
        ignoreWarnings: [
          {
            module: /@nestjs\//,
          },
        ],
        ...(runDevServer
          ? {
              devServer: {
                static: './dist',
              },
            }
          : {}),
        stats: {
          colors: true,
        },
        performance: {
          hints: false,
        },
        optimization: {
          minimize: false,
          splitChunks: {
            // include all types of chunks
            chunks: 'all',
          },
        },
        output: {
          globalObject: `typeof self !== 'undefined' ? self : this`,
          filename: '[name].mjs',
          path: path.join(process.cwd(), 'dist'),
          library: {
            // do not specify a `name` here
            type: 'module',
          },
        },
        experiments: {
          outputModule: true,
        },
        module: {
          rules: [
            {
              test: /.tsx?$/,
              use: {
                loader: 'swc-loader',
                options: {
                  minify: isProduction,
                  jsc: {
                    target: 'es2022',
                    parser: {
                      syntax: 'typescript',
                      decorators: true,
                      dynamicImport: true,
                    },
                    transform: {
                      legacyDecorator: true,
                      decoratorMetadata: true,
                    },
                  },
                },
              },
            },
          ],
        },
        plugins: [
          new BannerPlugin({
            banner: "import 'source-map-support/register.js';",
            raw: true,
            entryOnly: false,
          }),
          new BannerPlugin({
            banner: '/* eslint-disable */\n//prettier-ignore',
            raw: true,
          }),
          ...(runDevServer
            ? [
                new webpack.HotModuleReplacementPlugin(),
                new webpack.WatchIgnorePlugin({
                  paths: [/\.js$/, /\.d\.ts$/],
                }),
                new RunScriptWebpackPlugin({ name: `${path.basename(entry, '.ts')}.mjs`, autoRestart: false }),
              ]
            : []),
        ],
        resolve: {
          extensions: ['.tsx', '.ts', '.js', '.mjs'],
        },
        externals: [
          'perf_hooks',
          'fs/promises',
          ({ request, context }, callback) => {
            if (
              /^[^/.][a-zA-Z\-0-9./]+$/.test(request) &&
              !allowedPackages.some(regexp => regexp.test(request)) &&
              !includedInBundleExternals.includes(request)
            ) {
              return callback(null, `module ${request}`)
            }
    
            // Continue without externalizing the import
            return callback()
          },
        ],
      }
    
      return {
        ...baseConfig,
        entry: {
          [path.basename(entry, '.ts')]: runDevServer ? ['webpack/hot/poll?100', entry] : entry,
        },
      }
    }
    

    所以问题是,我该如何运行HMR服务器(或者应该如何?)以便正确获取HMR更新?我尝试了不同的方式,比如设置不同的 entry 具有 webpack-dev-server 并直接运行HMR服务器( const server = new webpackDevServer({ hot: false, client: false }, compiler) ),但这些都不起作用。我是不是看错了?

    除此之外,我有相当默认的Nest。JS应用程序:

    import 'reflect-metadata'
    import { NestFactory }          from '@nestjs/core'
    
    import { QualificationsModule } from './qualifications.module'
    
    async function bootstrap() {
      const app = await NestFactory.create(QualificationsModule)
      await app.listen(3000)
    
      if (module.hot) {
        module.hot.accept()
        module.hot.dispose(() => app.close())
      }
    }
    
    bootstrap()
    
    0 回复  |  直到 3 年前