webpack-dev-server未重新加载

yzckvree  于 2022-12-13  发布在  Webpack
关注(0)|答案(3)|浏览(235)

我使用的是Webpack 5,目前的设置如下:

  • webpack.prod.js -我在其中有一些用于生产的特定配置(例如,图像压缩、devtool、CSS缩小、特定的 meta标记值)
  • webpack.dev.js -我有一些特定的开发配置(例如,没有图像压缩,没有CSS缩小,特定的 meta标记值)

我目前面临的问题是,我无法让 *webpack dev服务器 * 实时重载工作(这适用于所有文件类型)。我已经通过了文档,但没有运气到目前为止。
据我所知,当处于开发模式时,webpack在内存中运行而不是在磁盘中运行(这应该更快,这很好!)。由于某种原因,监视器似乎没有对devServer.watchFiles配置中指定的文件的更改做出React。我希望webpack检测到一个typescript文件的更改,编译它并重新加载,但这并没有发生。
您可以在下面找到这两个文件的内容。

网络包产品js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const buildPath = path.resolve(__dirname, 'dist');

module.exports = {
  //devtool: 'source-map',
  entry: {
    index: "./src/index/index.ts",
    error: "./src/error/error.ts",
  },
  output: {
    filename: "js/[name].[contenthash].js",
    path: buildPath,
    clean: true,
  },
  module: {
    rules: [{
        test: /\.ts$/i,
        exclude: /node_modules/,
        use: "ts-loader",
      },
      {
        test: /\.html$/i,
        exclude: /node_modules/,
        use: "html-loader",
      },
      {
        test: /\.css$/i,
        exclude: /node_modules/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
        ]
      },
      {
        test: /\.png$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "img/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.(woff|woff2|ttf)$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "fonts/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.mp3$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "[name].[contenthash][ext]",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index/index.ejs",
      inject: "body",
      chunks: ["index"],
      filename: "index.html",
      meta: {
        "robots": {
          name: "robots",
          content: "index,follow"
        },
      },
    }),
    new HtmlWebpackPlugin({
      template: "./src/error/error.html",
      inject: "body",
      chunks: ["error"],
      filename: "error.html",
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].[contenthash].css",
      chunkFilename: "css/[id].[contenthash].css",
    }),
    new CopyPlugin({
      patterns: [{
        from: "src/robots.txt",
        to: "robots.txt",
      }, ],
    }),
  ],
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: true,
      }),
      new CssMinimizerPlugin(),
      new ImageMinimizerPlugin({
        minimizer: {
          implementation: ImageMinimizerPlugin.imageminMinify,
          options: {
            plugins: [
              ["imagemin-pngquant", {
                quality: [0.5, 0.9]
              }],
            ],
          },
        },
      }),
    ],
  },
};

webpack.dev.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    mode: "development",
    devtool: "eval-cheap-module-source-map",
    entry: {
        index: "./src/index/index.ts",
        error: "./src/error/error.ts",
    },
    devServer: {
        watchFiles: [path.resolve(__dirname, "src/**/*")],
        open: true,
    },
    module: {
        rules: [
            {
                test: /\.ts$/i,
                exclude: /node_modules/,
                use: "ts-loader",
            },
            {
                test: /\.html$/i,
                exclude: /node_modules/,
                use: "html-loader",
            },
            {
                test: /\.css$/i,
                exclude: /node_modules/,
                use: ["style-loader", "css-loader"]
            },
            {
                test: /\.png$/i,
                exclude: /node_modules/,
                type: "asset/resource",
                generator: {
                    filename: "img/[name].[contenthash][ext]",
                },
            },
            {
                test: /\.(woff|woff2|ttf)$/i,
                exclude: /node_modules/,
                type: "asset/resource",
                generator: {
                    filename: "fonts/[name].[contenthash][ext]",
                },
            },
            {
                test: /\.mp3$/i,
                exclude: /node_modules/,
                type: "asset/resource",
                generator: {
                    filename: "[name].[contenthash][ext]",
                },
            },
        ],
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: "./src/index/index.ejs",
            inject: "body",
            chunks: ["index"],
            filename: "index.html",
            meta: {
                "robots": { name: "robots", content: "noindex, nofollow" },
            },
        }),
        new HtmlWebpackPlugin({
            template: "./src/error/error.html",
            inject: "body",
            chunks: ["error"],
            filename: "error.html"
        }),
    ],
    optimization: {
        runtimeChunk: "single",
    },
};
zzwlnbp8

zzwlnbp81#

有几个地方我有点盲目,因为你没有添加一些关于你的tsconfig.json文件和你的package.json的描述,但我会尽我所能向你解释这里的关键点,然后解释解决方案。
ts-module
它是使用typescript模块编译文件的模块,它需要安装在应用程序中的typescript node_module和正确的tsconfig.json
出于实用的目的,我把我在以前的项目中使用的配置粘贴在下面--超级基本的,你可以根据你的项目来改进它--;配置没有什么特别之处,它不会影响HMR,但编译需要它。

{
  "compilerOptions": {
    "noImplicitAny": true,
    "removeComments": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "outDir": "./dist/",
    "sourceMap": true,
    "module": "commonjs",
    "target": "es6",
    "allowJs": true,
  },
  "includes": ["/**/*"]
}

webpack-dev-server

用于在本地环境中启动dev服务器的包,非常简单,应该与webpackwebpack-cli一起安装。
您的package.json可能有一个指向webpack.dev.js配置的start脚本:

"scripts" {
   "start": "webpack-dev-server --config ./webpack.dev.js",
}

Webpack配置

在实施“热重新加载”之前,需要考虑一些遗漏的事项

解析器配置

我在下面粘贴了一个预定义的列表,我为我的一个项目,你可以修改它,以接受更少/更多的扩展名,但想法是“告诉webpack”哪些文件将能够编译。
这将允许您导入具有这些扩展名的文件。

resolve: {
      extensions: [
        ".js",
        ".jsx",
        ".ts",
        ".tsx",
        ".less",
        ".css",
        ".json",
        ".mjs",
      ],
    }

在应用了这些之后,Webpack应该已经能够编译这些文件了; typescriptts-loader应该能够正确地查看您的文件。但是,这并不意味着**“热模块重新加载”**,这只是在发生变化时重新加载您的浏览器,开发服务器会自己执行“它的魔法”。

  • 我希望gif能证明配置是有效的 *

完整的Webpack配置如下所示:

const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  mode: "development",
  devtool: "eval-cheap-module-source-map",
  entry: {
    index: "./src/index/index.ts",
    error: "./src/error/error.ts",
  },
  resolve: {
    extensions: [
      ".js",
      ".jsx",
      ".ts",
      ".tsx",
      ".less",
      ".css",
      ".json",
      ".mjs",
    ],
  },
  module: {
    rules: [
      {
        test: /\.ts$/i,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
          },
        ],
      },
      {
        test: /\.html$/i,
        exclude: /node_modules/,
        use: "html-loader",
      },
      {
        test: /\.css$/i,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.png$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "img/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.(woff|woff2|ttf)$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "fonts/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.mp3$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "[name].[contenthash][ext]",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
        template: "./src/index/index.ejs",
        inject: "body",
        chunks: ["index"],
        filename: "index.html",
        meta: {
            "robots": { name: "robots", content: "noindex, nofollow" },
        },
    }),
    new HtmlWebpackPlugin({
        template: "./src/error/error.html",
        inject: "body",
        chunks: ["error"],
        filename: "error.html"
    })
  ],
  optimization: {
    runtimeChunk: "single",
  },
};

对于正确的Hot Module Reload --表示只更新更改的代码片段而不重新加载整个浏览器--

还需要一些调整,在互联网上有很多关于这个的资源,我会在最后列出,但是因为你没有使用babel --工作方式不同--你需要在你的webpack中提供一些更多的配置,同时删除其他属性。

更新ts加载程序配置

首先查看有关HMR的ts-loader文档https://github.com/TypeStrong/ts-loader#hot-module-replacement及其含义。
他们建议添加一个名为transpileOnly的配置,但是如果您检查有关该选项的规范,您将看到在下一次编译中丢失了一些类型检查,因此他们建议安装另一个包
建议使用transpileOnly和fork-ts-checker-webpack-plugin来再次进行完整的类型检查。
您的ts-loader规则应如下所示:

rules: [
      {
        test: /\.ts$/i,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
            },
          },
        ],
      },

以及您的插件:

plugins: [
    ..., // Your HTML plugins
    new ForkTsCheckerWebpackPlugin(),
  ],

启用热模块重新加载

这比看起来要容易,你需要考虑两个关键点:
1.让Webpack知道您需要HMR
1.让你的代码知道这将是热重载-听起来很有趣,但是的-

第一点非常简单,只需将以下配置添加到您的Webpack配置中:

devServer: {
    hot: true,
},

**但对于第二点,**这是一个有点棘手,与一个简单的调整,你可以做到这一点;最简单的方法是通过每个入口点创建一个新文件,文件可以根据您的意愿命名,但在本例中我将其命名为hot.ts,看起来像下面粘贴的代码:

// Inside of your index folder
require("./index");

if (module.hot) {
  module.hot.accept("./index.ts", function () {
    console.log("Hot reloading index");
    require("./index");
  });
}
// Inside of your error folder
require("./error");

if (module.hot) {
  module.hot.accept("./error.ts", function () {
    console.log("Hot reloading error");
    require("./error");
  });
}
  • 旁注:* 您会发现自己在使用module全局变量时遇到类型错误,要解决此问题,您需要安装以下类型npm i --save -D @types/node @types/webpack-env

在您的开发配置模式中--通常HRM用于开发而不是生产--您需要调整入口点:

entry: {
    index: "./src/index/hot.ts",
    error: "./src/error/hot.ts",
},

不覆盖HMR观察程序

我没有从文档中找到一个明确的答案,但是看起来你的devServer内部的watchFiles覆盖了HMR监视器,如果你删除它--即使从构建开发中删除,它在这个配置中也不会有什么不同--HMR应该可以顺利工作。
完成上述步骤后,您的webpack文件应类似于以下代码:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

module.exports = {
  mode: "development",
  devtool: "eval-cheap-module-source-map",
  entry: {
    index: "./src/index/hot.ts",
    error: "./src/error/hot.ts",
  },
  devServer: {
    hot: true,
  },
  resolve: {
    extensions: [
      ".js",
      ".jsx",
      ".ts",
      ".tsx",
      ".less",
      ".css",
      ".json",
      ".mjs",
    ],
  },
  module: {
    rules: [
      {
        test: /\.ts$/i,
        exclude: /node_modules/,
        use: [
          {
            loader: "ts-loader",
            options: {
              transpileOnly: true,
            },
          },
        ],
      },
      {
        test: /\.html$/i,
        exclude: /node_modules/,
        use: "html-loader",
      },
      {
        test: /\.css$/i,
        exclude: /node_modules/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.png$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "img/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.(woff|woff2|ttf)$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "fonts/[name].[contenthash][ext]",
        },
      },
      {
        test: /\.mp3$/i,
        exclude: /node_modules/,
        type: "asset/resource",
        generator: {
          filename: "[name].[contenthash][ext]",
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
        template: "./src/index/index.ejs",
        inject: "body",
        chunks: ["index"],
        filename: "index.html",
        meta: {
            "robots": { name: "robots", content: "noindex, nofollow" },
        },
    }),
    new HtmlWebpackPlugin({
        template: "./src/error/error.html",
        inject: "body",
        chunks: ["error"],
        filename: "error.html"
    }),
    new ForkTsCheckerWebpackPlugin(),
  ],
  optimization: {
    runtimeChunk: "single",
  },
};

包含工作示例的存储库:https://github.com/nicolasjuarezn/webpack-ts-example
配置工作示例:

有用的链接:

我希望这对你有帮助!

piok6c0g

piok6c0g2#

该问题与WSL有关。更具体地说,是在Windows文件系统(例如,/mnt/c/Users/MyUser/Documents/MyProject)上的WSL中运行webpack。
在将项目移动到WSL文件系统(例如,在/home/MyUser/MyProject)后,我能够让实时重新加载工作。
尽管this question提到了Parcel和Webpack,但它们是相似的。我发现答案提供了围绕这个问题的很好的上下文:https://stackoverflow.com/a/72786450/3685587

nr9pn0ug

nr9pn0ug3#

供Webpack 5使用

devServer: {
    watchFiles: ['src/**/*.php', 'public/**/*'],
  },

详情请访问https://webpack.js.org/configuration/dev-server/#devserverwatchfiles

相关问题