前端面试题 — webpack

1.webpack的安装和使用方式

  • 安装 Node.js 和 npm

    首先,确保你的计算机上安装了 Node.js 和 npm(Node 包管理器),因为 Webpack 是通过 npm 进行安装和管理的。

  • 创建项目目录并初始化 npm

    npm init -y

  • 安装 Webpack

    npm install webpack webpack-cli --save-dev

  • 创建 webpack 配置文件

    在项目根目录下创建一个名为 webpack.config.js 的文件,这是 Webpack 的配置文件,用来指示 Webpack 如何打包项目中的文件。

  • 运行打包命令

    npx webpack

2.webpack的热更新原理

  • 模块热替换(Hot Module Replacement):

    Webpack 的热更新基于模块热替换技术。它允许在应用程序运行过程中替换、添加或删除模块,而无需完全刷新页面。这种替换是在运行时进行的,可以使应用程序保持在当前状态下重新加载所需的部分。

  • HMR Runtime(热更新运行时):

   Webpack 会在构建过程中生成一个称为 HMR Runtime 的代码块。这段代码在运行时与应用程序一起加载,并通过 WebSocket 与开发服务器保持连接。HMR Runtime 负责管理模块热替换的逻辑。

  • 监视文件变化:

   在开发模式下,Webpack 会监视项目中各个文件的变化。当开发者保存文件时,Webpack 检测到文件发生变化,并触发重新编译过程。

  • 构建更新的模块:

   在重新编译过程中,Webpack 会确定哪些模块发生了变化,并构建更新的模块。这些更新的模块并不会替换现有的模块,而是生成一个更新的版本。

  • HMR 接口:

   HMR Runtime 与开发服务器建立了 WebSocket 连接,并通过 HMR 接口通信。当构建完成并生成了更新的模块时,Webpack 会将更新的模块信息通过 HMR 接口发送给 HMR Runtime。

  • 热更新处理:

   HMR Runtime 接收到更新的模块信息后,会根据更新的模块执行相应的操作。这可能涉及替换现有的模块、添加新模块或删除不再需要的模块。这样,应用程序的状态就得到了实时更新,而不需要完全刷新页面。

 

总的来说,Webpack 的热更新利用了模块热替换技术和 HMR Runtime,通过监视文件变化、构建更新的模块,并通过 WebSocket 与开发服务器进行通信,实现了代码的实时更新和页面局部刷新,提高了开发效率和体验。

3.webpack的常用loader

babel-loader:用于将ES6+的JavaScript代码转换为ES5代码,以便在旧版本浏览器中运行。

css-loader:用于解析CSS文件,并处理其中的import和url()等语法。

style-loader:将解析后的CSS代码以<style>标签的形式插入到HTML文件中。

file-loader:用于处理文件资源(如图片、字体等),并将其复制到输出目录中。

url-loader:类似于file-loader,但可以根据文件大小将文件转换为DataURL,以减少HTTP请求。

sass-loader:用于将Sass/SCSS代码转换为CSS代码。

less-loader:用于将Less代码转换为CSS代码。

postcss-loader:用于对CSS代码进行后处理,如自动添加浏览器前缀等。

vue-loader:用于解析和转换Vue单文件组件。

ts-loader:用于将TypeScript代码转换为JavaScript代码。

4.webpack的常用plugin以及作用

  • HtmlWebpackPlugin:

   自动生成 HTML 文件,并将打包后的 JavaScript 或 CSS 文件自动引入到 HTML 文件中。可配置参数包括模板文件、输出文件名、压缩选项等。

  • MiniCssExtractPlugin:

   将CSS 提取为单独的文件,并进行压缩和优化。通常与 CSS 相关的 loader 结合使用,如 style-loader、css-loader 等。

  • CleanWebpackPlugin:

   在每次构建之前清理输出目录(如 dist 目录),避免旧文件的累积。通常用于生产环境构建。

  • DefinePlugin:

   允许在编译时创建全局常量,可用于注入环境变量,例如配置开发环境和生产环境下的不同行为。

  • CopyWebpackPlugin:

   将文件或目录复制到构建输出目录,常用于复制静态资源文件,如图片、字体等。

  • OptimizeCssAssetsPlugin:

   用于优化和压缩 CSS 文件。通常与 MiniCssExtractPlugin 结合使用,用于生产环境构建。

  • WebpackBundleAnalyzer:

   析打包文件的大小和依赖关系,可视化构建结果,帮助优化代码和资源。

  • ProvidePlugin:

   自动加载模块,而不必到处 import 或 require。可以将全局变量注入到每个模块中,如将 jQuery 注入到每个模块中,使其无需手动引入。

  • CompressionWebpackPlugin:

   在构建过程中对资源文件进行 gzip 压缩,以减小文件体积,提高加载速度。

  • HotModuleReplacementPlugin:

   启用模块热替换(HMR)功能,实现代码修改后的实时更新,提高开发效率。

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader',
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      filename: 'index.html',
    }),
    new MiniCssExtractPlugin({
      filename: '[name].css',
      chunkFilename: '[id].css',
    }),
    new CleanWebpackPlugin(),
  ],
};

5.webpack的配置

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 自动引入资源插件  npm install --save-dev html-webpack-plugin
const MiniCssExtracPlugin = require("mini-css-extrac-plugin"); // css抽离
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");  //css压缩 npm install css-minimizer-webpack-plugin  --save-dev 
const TerserPlugin = require("terser-webpack-plugin"); // js压缩  npm install --save-dev terser-webpack-plugin
//加载toml、yarm、json5数据资源 npm install toml yarm json5 -D
const toml = require("toml");
const yarm = require("yarm");
const json5 = require("json5");

module.exports = (env) => {
  return {
    // 手动分离公共文件,通过配置成对象的方式实现多入口代码分割
    // entry: {
    //  index:{
    //    import:"./src/index.js",
    //    dependOn: "shared"  // 抽离公共文件
    //  },
    //  shared: "lodash"      // 公共的js文件
    // },
    // 多入口
      // entry: {
    //      pageOne: './src/pageOne/index.js',
    //      pageTwo: './src/pageTwo/index.js',
    //      pageThree: './src/pageThree/index.js',
      // },
    // 单入口
    entry: {
      index: "./src/index.js",
    },
    output: {
      filename: "scripts/[name].[contenthash].js", // 将所有的js放入同一个文件夹,并且根据文件名自动命名
      path: path.resolve(__dirname, "./dist"),
      clean: true, // 清除上一次的垃圾文件
      assetModuleFilename: "images/[contenthash][ext]", // 在images目录下,根据文件内容自动生成hash文件名
      publicPath: "https://*****.com/", // 公共路径(cdn域名或者本地localhost)
    },
    mode: env.prodection ? "prodection" : "development", // 生产环境或者开发环境 package.json 启动命令:npx webpack --env prodection
    devtool: "cheap-module-source-map",     // 真实报错文件指向,生产环境一般不开启sourcemap
    // 插件(非必要的,缺少也不影响项目打包)
    plugins: [
      new HtmlWebpackPlugin({
        template: "./index.html", // 模板
        filename: "app.html",
        inject: "body", // script 存在的位置
        hash: true, // 解决缓存
        minify: {
          removeAttributeQuotes: true, // 压缩,去掉引号
        },
      }),
      new MiniCssExtracPlugin({
        filename: "style/[contenthash].css",
      }),
    ],
    devServer: {
      static: "./dist", // 监听根目录文件变化,自动刷新页面插件 npm install --save-dev webpack-dev-server
      //反向代理
      proxy: {
        "/ajax": {
          target: "https:**********",
          ws: true,
          changeOrigin: true,
        },
      },
    },
    // 模块(必要的,缺少影响项目打包)
    module: {
      rules: [
        //资源模块类型我们称之为Asset Modules Type,总共有四种,来代替loader,分别是:
        // asset/resource:发送一个单独的文件并导出URL,替代file-loader
        // asset/inline:导出一个资源的data URI(base64),替代url-loader
        // asset/source:导出资源的源代码,之前通过使用raw-loader实现
        // asset:介于asset/resource和asset/inline之间, 之前通过url-loader+limit属性实现。
        {
          test: /\.(png|gif|jp?g|svg|webp|ico)$/, // 正则图片文件
          type: "asset",
          generator: {
            filename: "images/[contenthash][ext]", // 优先级高于 assetModuleFilename
          },
        },
        {
          // 支持less
          // npm install style-loader css-loader less-loader less --save-dev
          // 抽离 npm install mini-css-extrac-plugin  --save-dev   webpack5环境下构建的插件
          test: /\.(le|c)ss$/, // .less and .css
          use: [MiniCssExtracPlugin.loader,/* "style-loader", */ "css-loader","less-loader"],
        },
        {
          test: /\.(woff|woff2|eot|ttf|oft)$/, // 正则字体文件
          type: "asset/resource",
        },
        //加载csv、xml数据资源 npm install csv-loader xml-loader -D
        {
          test: /\.(csv|tsv)$/,
          use: "csv-loader",
        },
        {
          test: /\.xml$/,
          use: "xml-loader",
        },
        //加载toml、yarm、json5数据资源
        {
          test: /\.toml$/,
          type: "json",
          parser: {
            parse: toml.parse,
          },
        },
        {
          test: /\.yarm$/,
          type: "json",
          parser: {
            parse: yarm.parse,
          },
        },
        {
          test: /\.json5$/,
          type: "json",
          parser: {
            parse: json5.parse,
          },
        },
        // loader工具 支持数组方式链式调用,数组靠后的元素先执行
        {
          // 压缩图片
          //图片小于一定大小使用base64 否则使用file-loader产生真实图片 npm install url-loader --save-dev
          test: /\.(png|gif|jp?g|svg|webp|ico)$/, // 正则
          use: [
            {
              loader: "url-loader",
              options: {
                limit: 5000, //小于限定使用base64
                name: "home/images/[name].[hash:8].[ext]",
                publicPath: `../../`,
                esModule: false,
              },
            },
          ],
        },
        // 使用babel-loader npm install -D babel-loader @babel/core @babel/preset-env
        // regeneratorRuntime是webpack打包生成的全局辅助函数,由babel生成,用于兼容 async/await 的语法
        // npm install --save @babel/runtime
        // npm install --save-dev @babel/plugin-transform-runtime
        {
          test: /\.js$/,
          exclude: /node_modules/, // *业务代码里面可能会引入node_modules外部js,这些js不需要babel-loader编译,因此需要排除掉
          use: {
            loader: "babel-loader", // *引入babel-loader
            options: {
              presets: ["@babel/preset-env"], // *引入预设
              plugins: [
                [
                  "@babel/plugin-transform-runtime", // *配置插件信息
                ],
              ],
            },
          },
        },
      ],
    },
    optimization: {
      minimizer: [new CssMinimizerPlugin(),new TerserPlugin()],   //代码压缩 mode改为 production
      splitChunks: {
        // 缓存
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name: "vendors",
            chunks: "all", // 自动重复代码抽离
          },
        },
      },
    },
  };
};

6.如何利用webpack来优化前端性能?

  • 代码分割(Code Splitting):

   使用Webpack的代码分割功能,将代码拆分为多个小块,使得页面加载时只加载当前所需的代码,而不是一次性加载所有代码。 可以使用动态导入(Dynamic Import)或Webpack的SplitChunksPlugin来实现代码分割。

  • 懒加载(Lazy Loading):

   将页面中的一部分代码延迟加载,当用户需要时再加载对应的代码块,可以减少初始加载时间,提高页面加载速度。 结合Webpack的代码分割功能和动态导入来实现懒加载。

  • 压缩代码(Minification):

   使用Webpack的UglifyJsPlugin或terser-webpack-plugin等插件来压缩JavaScript代码,删除空白字符、注释等,减小文件体积,加快加载速度。

  • Tree Shaking:

   通过Webpack的Tree Shaking功能,删除项目中未被引用的代码,减小打包后的文件体积。 需要确保项目中的代码模块使用ES6模块语法,并且依赖于Webpack的Tree Shaking功能。

  • 资源优化:

   优化图片、字体等静态资源,使用Webpack的File Loader、URL Loader等加载器来处理图片、字体等文件,可以压缩、转换格式、生成Base64等。 使用Webpack的image-webpack-loader等插件来优化图片,压缩图片大小、提高加载速度。

  • 缓存优化:

   使用Webpack的文件指纹(File Hash)功能,给打包后的文件添加哈希值,使得文件内容发生改变时,文件名也会改变,可以有效利用浏览器缓存。 结合Webpack的output.filename和output.chunkFilename配置来实现文件指纹。

  • HTTP/2支持:

   使用Webpack的HTTP/2支持,可以通过Webpack的HMR(热模块替换)等功能来实现HTTP/2的多路复用特性,减少网络请求的数量,提高加载速度。

  • 代码优化:

   对代码进行优化,如避免使用过多的闭包、减少不必要的重复代码、优化循环等,可以提高代码的执行效率,加快页面渲染速度。

7.Webpack如何配置压缩代码?压缩了什么?

  • 在optimization配置项中来配置该插件作为压缩器进行压缩。
  • 在plugins里使用该插件进行压缩
  • js压缩:利用terser-webpack-plugin
  • css压缩:利用了optimize-css-assets-webpack-plugin 插件
  • 删除了console、注释、空格、换行、没有使用的css代码等

8.如何提高webpack的构建速度?

减少需要构建的文件或代码

  • HMR(Hot Module Replacement) 模块热替换只重新构建发生变化的模块 – 开发环境中
  • 缩小处理范围:合理利用这两个属性exclude:不需要处理的文件 和 include:需要处理的文件
  • babel缓存 第二次构建时,会读取之前的缓存,只重新构建变化的文件
  • 使用Dll进行分包 --> 分包方便按需加载

 

posted on 2024-04-15 15:45  萬事順意  阅读(103)  评论(0编辑  收藏  举报