初识webpack二

72 阅读5分钟

一、打包图片资源

webpack4打包图片资源如下所示:

1、打包图片资源需下载url-loader

npm i url-loader -D
  • 问题:默认处理不了html中img图片
  • 优点:减少请求数量(减轻服务器压力)
  • 缺点:图片体积会更大(文件请求速度更慢)
  • 问题: 因为url-loader默认使用es6模块化解析, 而html-loader引入图片是commonjs 解析时会出问题:[object Module]
  • 解决:关闭url-loader的es6模块化,使用commonjs解析,在options中配置esModule: false

2、处理html文件的img图片需下载html-loader

npm i html-loader -D

Tip:在webpack5中使用url-loader时,需要注意将type设置为:javascript/auto

此处引用官网解释:webpack官网

当在 webpack 5 中使用旧的 assets loader(如 file-loader/url-loader/raw-loader 等)和 asset 模块时,你可能想停止当前 asset 模块的处理,并再次启动处理,这可能会导致 asset 重复,你可以通过将 asset 模块的类型设置为 'javascript/auto' 来解决。

webpack.config.js配置如下:

options配置中limit:8 * 1024表示:当图片大小小于8KB,就会被base64处理

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

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
     
      {
        // 问题:默认处理不了html中img图片
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        // 下载url-loader file-loader
        loader: "url-loader",
        type: "javascript/auto",
        options: {
          // 图片大小小于8KB,就会被base64处理
          // 优点:减少请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit: 8 * 1024,
          // 问题:因为url-loader默认使用es6模块化解析, 而html-loader引入图片是commonjs
          // 解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          // 给图片重命名
          // [hash:9]取图片的hash的前9位
          // [ext]取文件原来扩展名
          name: "[hash:9].[ext]",
        },
      },
      {
        // 处理图片资源
        test: /\.html$/,
        // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
        loader: "html-loader",
        // type: "javascript/auto",
      },
    ],
  },
  optimization: {
    emitOnErrors: false,
  },
  plugins: [
    new HtmlWebpackPlugin({
      // 复制:‘./src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

webpack5打包图片资源如下所示:

  1. webpack5中使用资源模块对字体图标等资源文件进行处理,assets-module替代url-loader
  2. webpack5中处理html中的文件使用 html-withimg-loader替代html-loader

此处引用官网解释:

在 webpack 5 之前,通常使用:

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

webpack.config.js配置如下:

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

module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
        {
         // 处理图片资源  webpack5图片新打包方法
            test: /\.(jpg|png|gif)$/,
            // webpack5中使用assets-module(url-loader已废弃)
            type: 'asset',
            //配置解析器的选项
            parser: {
                dataUrlCondition: {
                //图片大小小于10KB,就会被base64处理
                    maxSize: 10 * 1024
                }
            },
            //配置生成器的选项
            generator: {
                //对图片重命名
                filename: 'img/[name].[hash:6][ext]',                
            }
        },
        {
          test: /\.html$/,
          // 处理html文件的img图片(负责引入img,从而能被url-loader处理)
          // webpack5中使用 html-withimg-loader代替
          // loader: 'html-loader'
          loader: 'html-withimg-loader'
      }     
    ],
  },
  optimization: {
    emitOnErrors: false,
  },
  plugins: [
    new HtmlWebpackPlugin({
      // 复制:‘./src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

        

二、打包其他资源

打包其他资源(除了html、js、css资源以外的其他资源)使用file-loader组件

npm i file-loader -D

例如打包字体图标资源:

html文件如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpack</title>
</head>
<body>
  <span  class="iconfont icon-auto"></span>
  <span  class="iconfont icon-all"></span>
  <span  class="iconfont icon-data"></span>
  <span  class="iconfont icon-rmb"></span>
</body>
</html>

index.js文件如下:

// 引入 iconfont 样式文件
import "./iconfont.css";

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 打包其他资源(除了html/js/css资源以外的其他资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less)$/,
        loader: "file-loader",
        type: "javascript/auto",
        options: {
          name: "[hash:9].[ext]",
          esModule: false,
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  mode: "development",
};

三、devServer

  • 开发服务器 devServer :用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
  • 特点:只会在内存中编译打包,不会有任何输出
  • 启动devServer指令: webpack server
  • 只需要在webpack.config.中配置devServer即可

webpack.config.js配置如下:

const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require("webpack"); // 用于访问内置插件
module.exports = {
  entry: "./src/index.js",
  output: {
    filename: "built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // 打包其他资源(除了html/js/css资源以外的其他资源)
      {
        // 排除css/js/html资源
        exclude: /\.(css|js|html|less)$/,
        loader: "file-loader",
        type: "javascript/auto",
        options: {
          name: "[hash:9].[ext]",
          esModule: false,
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
  ],
  //指定为开发环境模式
  mode: "development",
 
  devServer: {
    static: resolve(__dirname, "build"),
    // contentBase: resolve(__dirname, "build"),
    // 启动gzip压缩
    compress: true,
    //端口号
    port: 3000,
    // 自动打开浏览器
    open: true,
    hot: true,
    // host: "localhost",
  },
};

四、提取css成单独文件

  • 提取css成单独文件需下载插件:mini-css-extract-plugin
  • 在loader配置中使用MiniCssExtractPlugin.loader,这个loader取代style-loader,作用:提取js中的css成单独文件
  • plugins中配置MiniCssExtractPlugin
npm i mini-css-extract-plugin -D

webpack.config.js配置如下:

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

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",//将打包的js文件提取到js文件夹下
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 创建style标签,将样式放入
          // "style-loader",
          // 这个loader取代style-loader,作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          "css-loader",
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new MiniCssExtractPlugin({
      // 对输出文件进行重命名
      filename: "css/built.css",
    }),
  ],
  mode: "development",
};

五、css兼容处理

  • css兼容处理:postcss-->postcss-loader postcss-preset-env
  • css兼容性需要处理的是一些css3的样式属性在不同浏览器中的效果
  • 帮postcss找到package.json中browserlist里面的配置,通过配置加载指定的css兼容性样式
  • 在package.json中配置如下:
npm  i postcss-loader postcss-preset-env -D
"browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },

webpack4的webpack.config.js配置:

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

const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// 设置nodejs环境变量
// process.env.NODE_ENV = "development";

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 这个loader取代style-loader,作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          "css-loader",     
          // 使用loader的默认配置
          // 'postcss-loader'
          // 修改loader的配置
          {
            loader: "postcss-loader",
            options: {
             ident: "postcss",
             plugins: () => [
               // postcss插件
               require("postcss-preset-env")(),
             ],
             },
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new MiniCssExtractPlugin({
      // 对输出文件进行重命名
      filename: "css/built.css",
    }),
  ],
  mode: "development",
};

由于我是安装的webpack5的版本,所以用上面这种方法达不到预期效果,还需要安装一个loader:autoprefixer,并且新建一个postcss.config.js文件

postcss.config.js文件如下:

module.exports = {
  plugins: [
    require("postcss-preset-env"),
    require("autoprefixer")({
      overrideBrowserslist: [
        "defaults",
        "iOS 7.1",
        "Chrome>31",
        "ie>=8",
        "last 2 version",
        ">0%",
      ],
    }),
  ],
};

webpack.config.js文件中loader配置改为如下:

module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 这个loader取代style-loader,作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          "css-loader",        
          // 使用loader的默认配置
          // 'postcss-loader'
          // 修改loader的配置
          {
            loader: "postcss-loader",
          
          },
        ],
      },
    ],
  },

例如css文件中使用css3的属性

#box2{
  width: 100px;
  height: 100px;
  background: red;
  display: flex;
  backface-visibility: hidden;
}

经过兼容性处理打包后的css文件:

/*!***********************************************************************************************************!*\
  !*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./src/css/b.css ***!
  \***********************************************************************************************************/
#box2{
  width: 100px;
  height: 100px;
  background: red;
  display: -webkit-box;
  display: -webkit-flex;
  display: -moz-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-backface-visibility: hidden;
             -moz-backface-visibility: hidden;
          backface-visibility: hidden;
}

六、css压缩

压缩css需下载插件:optimize-css-assets-webpack-plugin

为了方便查看打包体积,安装了webpack-bundle-analyzer,可视化打包体积

npm i optimize-css-assets-webpack-plugin webpack-bundle-analyzer -D

webpack.config.js配置如下:

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

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// 压缩css
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

const BundleAnalyzerPlugin =
  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
// 设置nodejs环境变量
// process.env.NODE_ENV = "development";

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          // 这个loader取代style-loader,作用:提取js中的css成单独文件
          MiniCssExtractPlugin.loader,
          // 将css文件整合到js文件中
          "css-loader",         
          // 使用loader的默认配置
          // 'postcss-loader'
          // 修改loader的配置
          {
            loader: "postcss-loader",
           
          },
        ],
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    }),
    new MiniCssExtractPlugin({
      // 对输出文件进行重命名
      filename: "css/built.css",
    }),
    // 压缩css
    new OptimizeCssAssetsWebpackPlugin(),
    // 可视化打包体积
    new BundleAnalyzerPlugin(),
  ],
  mode: "development",
};