likes
comments
collection
share

Webpack配置,让你的代码飞得更高!(小鸟不一定会唱歌)

作者站长头像
站长
· 阅读数 17

开篇

Webpack是一种用于构建JavaScript应用程序的静态模块打包工具。它将应用程序的各个模块打包成一个或多个文件,以便于在浏览器中加载。Webpack提供了一个灵活的配置系统,让开发人员可以根据自己的需求来定制打包过程。

下面是Webpack配置的部分指南,让我们开始去了解了解吧。

安装Webpack

首先,我们需要安装WebpackWebpack可以通过npm来安装,执行以下命令即可:

npm install webpack webpack-cli --save-dev

创建Webpack配置文件

Webpack 的配置文件通常被命名为webpack.config.js,位于项目的根目录下。我们可以通过编写JavaScript代码来配置Webpack打包过程。

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  }
};

在此配置中,我们通过module.exports导出了一个对象,其中包含了两个属性:

  • entry: 表示Webpack应该从哪个文件开始打包。在此配置中,Webpack从名为index.js的文件开始打包。
  • output: 表示打包好的文件应该输出到哪里。在此配置中,打包好的文件将输出到dist目录下,文件名为bundle.js。

配置Loader

Loader是Webpack的核心概念之一。它允许Webpack在打包过程中对各种类型的文件进行转换处理。通过使用不同的Loader,我们可以让Webpack打包处理不同种类的文件,如CSS、图片、字体等。

下面介绍一下Loader的常见配置选项:

  1. test: 用于匹配需要 Loader 转换的文件。可以是正则表达式,也可以是一个文件路径。比如,test: /.js$/ 表示匹配所有的 .js 文件。
  2. exclude: 这个表示排除不需要匹配的文件夹或文件。如,exclude: /node_modules/ 表示忽略 node_modules 文件夹下的所有内容。
  3. include: 这个表示只对需要匹配的文件夹或文件进行匹配。如, include: /src/ 只匹配 src 文件夹下的内容。
  4. use: 用于指定 Loader 名称,可以是一个字符串或数组。它可以是预设的 Loader 名称,也可以是自定义的 Loader 名称。当需要使用多个 Loader 时,可以使用数组进行列表。
  5. options: 这个用于指定 Loader 的参数,通常用于传递额外的选项。

下面是一个例子,使用css-loaderstyle-loader处理CSS文件:

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          }
        ]
      }
    ]
  }
};

在此配置中,我们使用了两个Loader来处理CSS文件。首先,Webpack使用css-loaderCSS文件转换为JavaScript模块,然后使用style-loader将该模块作为样式添加到HTML文件中。

配置Babel

Babel是一种JavaScript编译器,它可以将最新版本的JavaScript转换为向后兼容的代码,以便于在老旧的浏览器上运行。我们可以使用Webpackbabel-loader来配置Babel转换过程。

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
};

在此配置中,我们使用babel-loader来处理所有的.js文件。babel-loader使用options选项来配置Babel的preset。在此配置中,我们使用了@babel/preset-env,它可以根据目标浏览器和项目中使用的JavaScript特性来自动选择转换规则。

配置Plugin

Plugin是Webpack的另一个核心概念。它们可以用于执行各种任务,如优化打包过程、引入全局变量、对输出文件进行处理等。

下面是一个例子,使用HtmlWebpackPlugin插件自动生成HTML文件:

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

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          {
            loader: 'style-loader'
          },
          {
            loader: 'css-loader'
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ]
};

在此配置中,我们使用HtmlWebpackPlugin插件来生成一个HTML文件。该插件将使用index.html文件中的模板进行生成。

处理环境变量

在开发和生产环境下,我们可能需要使用不同的配置参数。Webpack提供了处理环境变量的机制,以便于灵活配置打包过程。

下面是一个例子,使用webpack-merge插件来合并不同环境下的配置:

const merge = require('webpack-merge');
const commonConfig = require('./webpack.common.config.js');

module.exports = (env, argv) => {
  if (argv.mode === 'development') {
    return merge(commonConfig, {
      devtool: 'inline-source-map',
      devServer: {
        contentBase: './dist'
      }
    });
  }
  if (argv.mode === 'production') {
    return merge(commonConfig, {
      devtool: 'source-map'
    });
  }
};

在此配置中,我们首先通过require导入了webpack-merge插件和一个名为webpack.common.config.js的公共配置文件。然后,我们通过module.exports导出一个函数,该函数将根据不同的环境变量返回不同的配置。

配置TypeScript

TypeScript是一种JavaScript的超集,它添加了类型检查和其他语言特性,使得代码更加稳健可靠。我们可以使用Webpack的ts-loader来配置TypeScript转换过程。

module.exports = {
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.ts', '.js']
  },
  module: {
    rules: [
      {
        test: /.ts$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'ts-loader'
        }
      }
    ]
  }
};

在此配置中,我们使用了ts-loader来处理所有的.ts文件。ts-loader会根据tsconfig.json中的配置来转换TypeScript代码。

配置React

React是一种流行的JavaScript库,可以用于构建复杂的用户界面。我们可以使用Webpack的babel-loader来处理React代码,并配置React的转换规则。

module.exports = {
  entry: './src/index.jsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  resolve: {
    extensions: ['.js', '.jsx']
  },
  module: {
    rules: [
      {
        test: /.(js|jsx)$/,
        exclude: /(node_modules)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
    ]
  }
};

在此配置中,我们使用了babel-loader来处理所有的.js.jsx文件。我们使用了@babel/preset-env来处理JavaScript代码,使用了@babel/preset-react来处理React代码。

配置CSS

Webpack可以处理各种类型的静态资源,包括CSS文件。我们可以使用Webpack的css-loaderstyle-loader来配置CSS的转换和添加。

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader']
      }
    ]
  }
};

在此配置中,我们使用了style-loadercss-loader来处理CSS文件。css-loader会将CSS转换为JavaScript模块,style-loader会将该模块作为样式添加到HTML文件中。

配置图片

Webpack可以通过file-loaderurl-loader将图像转换为模块,并插入到JavaScript代码或样式表中。

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.(png|jpe?g|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: '[name].[hash].[ext]',
              outputPath: 'images'
            },
          },
        ],
      },
    ],
  },
};

在此配置中,我们使用了url-loader,它可以将小的图像文件转换为base64 URL,并将大的图像文件作为物理文件复制到输出目录。在此配置中,我们设置了limit选项,如果文件大小小于8192B,则图像文件将转换为base64,否则文件将被复制到输出目录,文件名由原始名称哈希扩展名构成,并且存储在images目录下。

配置字体

Webpack可以通过file-loaderurl-loader将字体转换为模块,并插入到JavaScript代码或样式表中。

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
        generator: {
          filename: 'fonts/[name].[hash][ext]'
        }
      },
    ],
  },
};

在此配置中,我们使用了asset/resource生成器类型,它可以将字体文件复制到输出目录,并将文件名由原始名称、哈希和扩展名构成,并且存储在fonts目录下。

配置代码分割

Webpack可以将代码分割成多个块,以便按需加载和减少初始加载时间。

module.exports = {
  // ...
  optimization: {
    splitChunks: {
      chunks: 'all',
      minSize: 10000,
      maxSize: 250000,
      cacheGroups: {
        defaultVendors: {
          test: /[\/]node_modules[\/]/,
          priority: -10
        },
        default: {
          minChunks: 2,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
};

在此配置中,我们使用了splitChunks选项来配置代码分割。我们设置了chunks选项为’all’,可以将代码分割为同步和异步块。我们还设置了minSizemaxSize选项,指定了块的最小和最大大小。我们定义了两个缓存组,一个是defaultVendors缓存组,用于将来自node_modules目录的代码提取到单独的块中,一个是default缓存组,用于将多个块共享的模块提取到单独的块中

配置无需打包的库

有些库是我们不需要打包的,因为它们的大小很大,并且它们不会经常更改。我们可以使用Webpack的externals选项来忽略这些库,并从CDN或其他外部源加载它们。

module.exports = {
  // ...
  externals: {
    jquery: 'jQuery'
  },
};

在此配置中,我们使用了externals选项,将jquery库从打包中排除,并将它视为全局变量’jQuery’。这意味着我们不需要在Webpack打包中包含jquery,因为我们将在HTML文件中使用CDN或其他外部源加载它。

配置多页面应用

除了单页面应用之外,Webpack也可以用于构建多页面应用。我们可以使用Webpack的entry选项来指定每个页面的入口文件,并使用HtmlWebpackPlugin生成每个页面所需的HTML文件。

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    home: './src/home.js',
    about: './src/about.js',
    contact: './src/contact.js',
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'home.html',
      template: './src/home.html',
      chunks: ['home']
    }),
    new HtmlWebpackPlugin({
      filename: 'about.html',
      template: './src/about.html',
      chunks: ['about']
    }),
    new HtmlWebpackPlugin({
      filename: 'contact.html',
      template: './src/contact.html',
      chunks: ['contact']
    }),
  ],
};

在这个示例中,我们使用Webpack的entry选项指定了三个页面的入口文件。我们还使用HtmlWebpackPlugin插件生成了每个页面所需的HTML文件,并指定了与当前页面相关的块,以确保Webpack只添加正确的JavaScript代码。

配置热模块替换

Webpack可以使用Hot Module Replacement(HMR)来在运行时更新模块而不需要重新加载整个页面。我们可以通过Webpack Dev Server和HotModuleReplacementPlugin来启用热模块替换。

// webpack.config.js
const webpack = require('webpack');

module.exports = {
  // ...
  devServer: {
    contentBase: './dist',
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ]
};

在这个示例中,我们使用Webpack Dev Server的contentBase选项指定了应用程序的基本目录,并启用了hot选项以启用HMR。我们还使用webpack的HotModuleReplacementPlugin插件来启用模块热替换。

配置代码格式化

我们可以使用PrettierESLint等工具来格式化我们的代码。Webpack可以使用loaderplugin为我们的代码自动格式化。

// webpack.config.js
module.exports = {
  // ...
  module: {
    rules: [
      {
        // Use Prettier to format JavaScript code
        enforce: 'pre',
        test: /.js$/,
        loader: 'prettier-loader',
        options: {
          // Prettier options
        }
      },
      {
        // Use ESLint to lint and format JavaScript code
        enforce: 'pre',
        test: /.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // ESLint options
        }
      },
    ],
  },
  plugins: [
    // Use Prettier to format HTML and CSS code
    new PrettierPlugin({
      // Prettier options
    }),
  ],
};

在这个示例中,我们使用PrettierESLint来格式化和检查我们的代码。我们定义了两个规则,一个使用prettier-loader来使用Prettier格式化我们的JavaScript代码,并使用eslint-loader来使用ESLint检查和格式化代码。我们还使用PrettierPlugin插件来格式化我们的HTML和CSS代码。这些工具都需要安装并正确配置,才能在Webpack中使用。

webpack性能优化

Webpack在打包过程中可能会产生大量的中间文件,导致打包速度变慢。为了优化Webpack的性能,我们需要进行一些额外的配置。

下面是一些优化Webpack性能的方法:

  • 使用更高版本的Webpack和相关工具,以获得更好的性能表现。
  • 通过Tree Shaking的方式精简打包后的文件,去掉未使用的代码和模块。
  • uglifyjs-webpack-pluginterser-webpack-plugin压缩打包后的文件,以减小文件大小。
  • 使用cache-loaderhard-source-webpack-plugin将中间文件缓存到内存或者硬盘中,以加快打包速度。
  • 在开发环境下使用webpack-dev-serverwebpack-dev-middleware提高打包性能。这两个工具允许我们将文件打包到内存中,以避免多次读写磁盘文件。

分包

在Webpack中,可以使用SplitChunksPlugin进行分包,将公共模块提取出来单独生成一个文件,避免每个页面都加载相同的代码。具体可以按照以下步骤进行配置:

  1. optimization中添加splitChunks选项,用于配置分包规则。
optimization: {
  splitChunks: {
    chunks: 'all', // 所有类型的chunks都被考虑
    minSize: 30000, // 生成的Chunk最小的大小
    minChunks: 1, // 被多少模块共享
    maxAsyncRequests: 5, // 按需加载的最大并行请求数
    maxInitialRequests: 3, // 初始加载的最大并行请求数
    name: true, // 生成的Chunk名
    cacheGroups: {
      vendors: { // 第三方资源
        test: /[\/]node_modules[\/]/,
        priority: -10,
        filename: 'vendors.js'
      },
      default: { // 其他公共模块
        minChunks: 2,
        priority: -20,
        reuseExistingChunk: true, // 公共模块之间是否可以复用
        filename: 'common.js'
      }
    }
  }
}

chunks指定需要提取的Chunk类型,minSize指定生成的Chunk最小大小,minChunks指定被多少模块共享才可以被提取,cacheGroups用于配置不同类型的Chunk的提取规则,将公共模块提取出来单独成为一个文件。

  1. output中添加filename选项,用于指定生成的文件名。
output: {
  filename: '[name].js',
  path: path.resolve(__dirname, 'dist')
}

[name]会被替换为Chunk的名称。

完成以上配置后,再次重新构建时,Webpack会根据分包规则将公共模块提取出来单独生成文件。

总结

别让你的代码像一只笨重的企鹅,赶快配置Webpack,让它像一只轻盈的小鸟,飞向更高的层次!(小鸟不一定会唱歌)