03-Webpack常用loader

nobility 发布于 2021-12-20 844 次阅读


Webpack常用loader

打包静态资源

file-loader

使用file-loader可打包任意类型文件,file-loade的打包形式实际上就是将要打包的文件复制一份一模一样的文件到输出目录的根目录中,默认使用根据文件内容生成的32位hash命名,在源码中引入的资源文件,其实就是引入了该文件路径(打包后文件路径)

使用file-loader首先需要使用npm install file-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: { //模块打包配置
    rules: [{ //规则数组,其中都是一个个的规则对象
      test: /\.(jpg|png|gif)$/, //使用正则匹配到以jpg或png或gif结尾的文件
      use: {
        loader: "file-loader", //使用file-loader进行打包
        options: { //使用file-loader的其他选项
          //这些选项除啦接收字符串外还可以接收一个函数,具体参照webpack官网即可
          name: "[name]_[hash:5].[ext]", //自定义资源输出名,使用占位符的形式
          outputPath: "images/" //自定义资源输出路径,相对于输出根路径目录
        }
      }
    }]
  }
}

可使用占位符为输出文件自定义命名,占位符都是使用方括号进行包裹,常用的占位符如下:

占位符 描述
[name] 原文件名
[ext] 原文件后缀
[hash] 文件内容生成的hash,也可控制hash值的位数,比如:使用[hash:5]可取前5位hash值

url-loader

具有file-loader的所有功能,并且在此基础上还可以将资源文件转化成base64编码的字符串,嵌入到引入该模块的文件中

使用url-loader首先需要使用npm install url-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: { //模块打包配置
    rules: [{ //规则数组,其中都是一个个的规则对象
      test: /\.(jpg|png|gif)$/, //使用正则匹配到以jpg或png或gif结尾的文件
      use: {
        loader: "url-loader", //使用url-loader进行打包
        options: { //使用url-loader的其他选项
          name: "[name]_[hash:5].[ext]",
          outputPath: "images/",
          limit: 8096 //资源文件小于8096字节时才会转化成base64字符串
        }
      }
    }]
  }
}

html-loader

HtmlWebpackPlugin用的html模板中使用到的资源打包交由url-loader或file-loader处理,也可以将html文件引入js当字符串处理

使用url-loader首先需要使用npm install html-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

webpack4需要将url-loader中需要设置esModule=false,webpack5需要将output中设置publicPath: "./"

const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin"); //引入HtmlWebpackPlugin插件
module.exports = {
  entry: {
    main: "./index.js"
  },
  module: {
    rules: [{	//规则数组,其中都是一个个的规则对象
        test: /\.(jpg|png|gif)$/,	//使用正则匹配到以jpg或png或gif结尾的文件
        use: {
          loader: "url-loader",	 //使用url-loader进行打包
          options: {
            name: "[name]_[hash:5].[ext]",
            outputPath: "images/",
            limit: 8096	//资源文件小于8096字节时才会转化成base64字符串
          }
        }
      },
      {
        test: /\.html$/,	//使用正则匹配到以html结尾的文件
        loader: 'html-loader',	//使用html-loader进行打包
      },
    ],
  },
  plugins: [new HtmlWebpackPlugin({	//在插件数组中实例化该插件提供的对象
    template: "./index.html"  //设置html模板的路径
  })],
  output: {
    filename: "main.js", //输出文件名
    path: path.resolve(__dirname, "dist"), //输出文件根目录
    publicPath: "./"
  }
}

打包样式资源

css-loader

使用css-loader可打包css文件,会自动处理css文件之间的依赖(@import语句引入的其他css文件),css-loader的打包形式实际上就是将要打包的css文件中的字符串内容读入并转化成一个对象,使用toString()方法可获得css中的字符串内容,在源码中引入的css文件,其实就是引入了该css文件对象

使用css-loader首先需要使用npm install css-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.css$/,	//使用正则匹配到以css结尾的文件
      use: "css-loader"	//使用css-loader进行打包
    }]
  }
}

style-loader

使用style-loader向打包后的js文件中添加代码,用于将使用css-loader打包后的css文件对象中内容自动挂载到head标签中的的style标签内,与css-loader联合使用,但是需要注意使用顺序,webpack在使用loader时是从后往前进行使用的

使用style-loader首先需要使用npm install style-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.css$/,	//使用正则匹配到以css结尾的文件
      use: [	//使用多个loader进行打包时要使用数组形式
        "style-loader",	//使用style-loader将css内容挂载到head标签的style标签内容
        "css-loader"	//使用css-loader进行打包
        //注意使用顺序是从后向前的,因为style-loader依赖css-loader,所以css-loader在后style-loader在前
      ]
    }]
  }
}

CSS模块化

使用css-loader中的modules配置参数,该参数的意义是:是否开启css模块化,最好再使用style-loader对进行处理,因为仅使用css-loader处理的CSS文件只是把类名和ID名改啦,无法直接使用

要注意的是:因为开启模块化后css-loader会将CSS文件中的类名和ID名改掉,所以原来页面中的标签引用的CSS类名会失效,也就是说这些类名的添加只能借助与js

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.css$/, //使用正则匹配到以css结尾的文件
      use: [
        "style-loader",	//使用style-loader将css内容挂载到head标签的style标签内容
        { //对loader配置时,需要使用对象的方式
          loader: "css-loader", //使用css-loader进行打包
          options: { modules: true } //配置开启css模块化
        }
      ]
    }]
  }
}

开启css模块化打包后,引入的css文件就会成为一个包含该css文件中所有类和ID选择器的映射对象(元素选择器会忽略),每个模块生成的选择器映射对象中的值都是不同的,所以不同模块下使用CSS类名是不会冲突的

/*	CSS文件如下
.root {
    width: 100px;
    height: 100px;
    background-color: red;
}
*/
import css from "index.css";
console.log(css);	//{root: "_3X0Aom5jxsrMjeo9F0A3Gr"}
var root = document.getElementById("root");
root.classList.add(css.root);	//此时就会为该DOM节点添加 _3X0Aom5jxsrMjeo9F0A3Gr 类名让CSS生效

css-loader中importLoaders参数的意义:设置在css-loader之前使用的loader的数量,比如在使用sass或less中,css-loader是在其他loader之后执行的,在sass或less中引入其他样式文件时,可能就不会执行后续的loader了,所以该值就可以决定引入的样式文件接着从头走loader

sass-loader

sass-loader将Sass/Scss文件打包成css文件,该loader依赖sass编译环境,所以需要预先安装Dart Sass或Node Sass包,官方推荐Dart Sass

  • 使用npm install sass -D可安装Dart Sass
  • 使用npm install node-sass -D可安装Node Sass,安装较慢

使用sass-loader首先需要使用npm install sass-loader -D安装该loader,同时与css-loader和style-loader联合使用,需要注意使用顺序,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.(scss|sass)$/,	//使用正则匹配到以scss或sass结尾的文件
      use: [	//使用多个loader进行打包时要使用数组形式
        "style-loader",	//使用style-loader将css内容挂载到head标签的style标签内容
        { //对loader配置时,需要使用对象的方式
          loader: "css-loader", //使用css-loader对css文件进行打包
          options: { importLoaders : 1 }  //对于@import语句引入的文件,需要再向后走一个loader,即在经过sass-loader处理
        },
        "sass-loader"	//使用sass-loader对scss或sass文件进行编译打包
      ]
    }]
  }
}

less-loader

less-loader将less文件打包成css文件,该loader依赖less编译环境,所以需要预先安装Less,使用npm install less -D可安装Less

使用less-loader首先需要使用npm install less-loader -D安装该loader,同时与css-loader和style-loader联合使用,需要注意使用顺序,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.less$/,	//使用正则匹配到以less结尾的文件
      use: [	//使用多个loader进行打包时要使用数组形式
        "style-loader",	//使用style-loader将css内容挂载到head标签的style标签内容
        { //对loader配置时,需要使用对象的方式
          loader: "css-loader", //使用css-loader对css文件进行打包
          options: { importLoaders : 1 }  //对于@import语句引入的文件,需要再向后走一个loader,即在经过less-loader处理
        },
        "less-loader"	//使用less-loader对less文件进行编译打包
      ]
    }]
  }
}

postcss-loader

使用PostCSS工具处理CSS的loader,PostCSS是一款使用插件去转换CSS的工具,所以需要预先安装PostCSS,使用npm install postcss -D可安装可安装该工具

使用postcss-loader首先需要使用npm install postcss-loader -D安装该loader,同时与css-loader和style-loader联合使用(也可以同时使用sass或less,以sess为例),需要注意使用顺序,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: {
    main: "./index.js" //入口文件路径
  },
  module: {
    rules: [{
      test: /\.(scss|sass)$/,	//使用正则匹配到以scss或sass结尾的文件
      use: [	//使用多个loader进行打包时要使用数组形式
        "style-loader",	//使用style-loader将css内容挂载到head标签的style标签内容
        { //对loader配置时,需要使用对象的方式
          loader: "css-loader", //使用css-loader对css文件进行打包
          options: { importLoaders : 2 }  //对于@import语句引入的文件,需要再向后走一个loader,即在经过postcss-loader和sass-loader处理
        },
        "postcss-loader",	//使用postcss-loader处理css文件
        "sass-loader"	//使用sass-loader对scss或sass文件进行编译打包
      ]
    }]
  }
}

现在使用PostCSS是没有任何作用的,若想使用PostCSS中的插件,需要在创建一个postcss.config.js配置文件才能使用到PostCSS中的插件

autoprefixer

autoprefixer是PostCSS的一个插件,用于自动为CSS添加浏览器厂商前缀,使用autoprefixer首先需要使用npm install autoprefixer -D安装该插件,并在postcss.config.js中编写以下规则

const autoprefixer = require("autoprefixer");   //引入autoprefixer插件
module.exports = {
  plugins: [ 
    autoprefixer({
      browsers: [">0%"]	//要兼容的浏览器规则
    })
  ]
}
// "development": [	//开发环境下的配置
//   "last 1 chrome version",
//   "last 1 firefox version",
//   "last 1 safari version"
// ],
// "production": [	//生产环境下配置
//   ">0.2%",
//   "not dead",
//   "not op_mini all"
// ]
postcss-cssnext

postcss-cssnext是PostCSS的一个插件,用于将高级的CSS语法转化为浏览器能识别的CSS语法,比如CSS变量var()语法,使用postcss-cssnext首先需要使用npm install postcss-cssnext -D安装该插件,并在postcss.config.js中编写以下规则

const cssnext = require("postcss-cssnext"); //引入postcss-cssnext插件
module.exports = {
  plugins: [cssnext]
}
postcss-sprites

postcss-sprites是PostCSS的一个插件,用于将图片自动转化为精灵图,使用postcss-sprites首先需要使用npm install postcss-sprites -D安装该插件,并在postcss.config.js中编写以下规则

const sprites = require("postcss-sprites"); //引入postcss-cssnext插件
module.exports = {
  plugins: [ 
    sprites({
      spritePath: "./public/images/"	//设置生成的精灵图路径
    })
  ]
}

注意:该插件与WebpackDevServer或watch模式自动打包功能同时使用会造成一直打包的死循环,可为WebpackDevServer和watch增加以下配置

/* WebpackDevServer的配置 */
devServer{
  watchOptions: {	//监视选项
   contentBase: path.join(__dirname, 'dist'),  //指定输出目录
   ignored: /(node_modules|sprite)/	//忽略node_modules和sprite的变化
  }
},
/* --watch参数命令的配置 */  
watchOptions: {
  ignored: /(node_modules|sprite)/	//忽略node_modules和sprite的变化
}

打包js文件

babel-loader

babel-loader将ES6的语法转化成ES5的语法,兼容低版本浏览器,该loader依赖babel的编译环境,所以需要预先安装@babel/core核心库,使用npm install @babel/core -D可安装babel编译环境,而且还需要更具转化需求安装相应的库,具体如下:

  • npm install @babel/preset-env -D:仅做简单预处理,简单语法翻译,不会处理像promise这样的高级语法
  • npm install @babel/polyfill:以依赖模块的形式处理像promise这样的高级语法,需要在页面引入(依赖core-js@2.6.11但是无需手动安装,会自动安装)
  • npm install core-js:用于按需处理像promise这样的高级语法,手动安装corejs的更高版本

使用babel-loader首先需要使用npm install babel-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

简单处理配置
module.exports = {
  entry: "./index.js",	//入口文件路径
  module: {
    rules: [{
      test: /\.js$/,	//使用正则匹配到以js结尾的文件
      exclude: /node_modules/,	//排除掉node_modules中第三方模块的js文件
      loader: "babel-loader",	//使用babel-loader对js文件进行编译打包
      options: {
        presets: ["@babel/preset-env"],	//使用@babel/preset-env做预处理
        cacheDirectory: true	//开启构建缓存,第二次构建时更快
      }
    }]
  }
}
填充处理

下载@babel/polyfill包后直接在js文件中引入即可,问题就是编译出的代码容量过大,一般也不会使用

import "@babel/polyfill";	//引入@babel/polyfill模块
按需填充

下载core-js包后需要修改以下配置,问题就是会在注册全局变量,在编写框架类库时,不希望污染全局变量,一般用这种配置就够了

module.exports = {
  entry: "./index.js",	//入口文件路径
  module: {
    rules: [{
      test: /\.js$/, //使用正则匹配到以js结尾的文件
      exclude: /node_modules/, //排除掉node_modules中第三方模块的js文件
      loader: "babel-loader", //使用babel-loader对js文件进行编译打包
      options: {
        presets: [["@babel/preset-env", { //注意写法是嵌套数组
            targets: { //要兼容的目标
              chrome: "67", //谷歌浏览器
              firefox: "60", //火狐浏览器
              safari: "11.1", //苹果浏览器
              ie: "9", //ie浏览器
              edge: "17" //edge浏览器
            },
            corejs: { version: 3 },	//指定corejs版本
            useBuiltIns: "usage" //使用按需构建填充
          }]],
        cacheDirectory: true	//开启构建缓存,第二次构建时更快
      }
    }]
  }
}
Library
运行时填充

在编写框架类库时,不会污染全局变量

  1. 首先使用npm install @babel/plugin-transform-runtime -D 安装该插件
  2. 再使用npm install @babel/runtime安装该模块
  3. 再使用npm install @babel/runtime-corejs2安装该模块
module.exports = {
  entry: "./index.js",  //入口文件路径
  module: {
    rules: [{
      test: /\.js$/, //使用正则匹配到以js结尾的文件
      exclude: /node_modules/, //排除掉node_modules中第三方模块的js文件
      loader: "babel-loader", //使用babel-loader对js文件进行编译打包
      options: {
        plugins: [["@babel/plugin-transform-runtime", { //注意写法是嵌套数组
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
          }]],
        cacheDirectory: true	//开启构建缓存,第二次构建时更快
      }
    }]
  }
}
Library打包

若是对于库打包,打包过后的文件是需要别人使用的,所以需要向外暴露变量,才能被使用,所以可以进行以下配置

const path = require("path");
module.exports = {
  entry: "./index.js",	//入口文件路径
  output: {
    filename: "main.js", //输出文件名
    path: path.resolve(__dirname, "dist"), //输出文件根目录
    library: "main",	//用户可以使用script标签引入该库,并且变量名为main
    libraryTarget: "umd"	//用户可以使用CommandJS、ES6、AMD、CMD模块化引入该库,umd即通用方式的简写
    //libraryTarget也可以设置 commandjs this window global 来指定该库的使用方式,一般会使用umd
  },
  mode: "production", //生产环境
}

若在库中又引入了其他的库,以jQuery为例,又不希望将其他库一起做打包,而希望用户自己引入时,可以增加externals参数进行配置

const path = require("path");
module.exports = {
  entry: "./index.js",	//入口文件路径
  output: {
    filename: "main.js", //输出文件名
    path: path.resolve(__dirname, "dist"), //输出文件根目录
    library: "main",	//用户可以使用script标签引入该库,并且变量名为main
    libraryTarget: "umd"	//用户可以使用CommandJS、ES6、AMD、CMD模块化引入该库,umd即通用方式的简写
    //libraryTarget也可以设置 commandjs this window global 来指定该库的使用方式,一般会使用umd
  },
  externals: {
    // jquery: ["jQuery"], //忽略jquery库的打包,并且需要依赖外部变量jQuery
    jquery: {
      commonjs: 'jquery',	//使用commonjs引入时需要将库依赖的jQuery库名为jQuery,即 const jquery = require("jquery")
      root: '$',	//使用script标签引入时,需要jQuery全局变量为jQuery
    }
  }
  mode: "production", //生产环境
}
babelrc

对于使用babel-loader中options选项过于冗长时,可以在项目根目录添加一个.babelrc文件,将options对象抽离到该文件中,在webpack中省略options参数即可

{
  plugins: [["@babel/plugin-transform-runtime", { //注意写法是嵌套数组
      "corejs": 2,
      "helpers": true,
      "regenerator": true,
      "useESModules": false
    }]],
  cacheDirectory: true	//开启构建缓存,第二次构建时更快
}

eslint-loader

eslint-loader用于检测js代码写的是否规范,该loader依赖eslint检测环境,所以需要预先安装eslint,使用npm install eslint -D可安装eslint,安装后使用npx eslint --init命令,会以提问的形式初始化eslint规范

使用eslint-loader首先需要使用npm install eslint-loader -D安装该loader,并编写以下规则(输出和模式采用默认了),若与babel-loader同时使用,需要先使用eslint-loader,若顺序不对时间,可以使用force: "pre"让该loader提前执行

module.exports = {
  entry: "./index.js", //入口文件路径
  module: {
    rules: [{
      test: /\.js$/, //使用正则匹配到以js结尾的文件
      exclude: /node_modules/, //排除掉node_modules中第三方模块的js文件
      use: [{
        loader: "babel-loader", //使用babel-loader对js文件进行编译打包
        options: {
          presets: ["@babel/preset-env"], //使用@babel/preset-env做预处理
          cacheDirectory: true //开启构建缓存,第二次构建时更快
        }
      }, {
        loader: "eslint-loader",
        force: "pre",	//该loader提前执行
        options: {
          fix: true, //自动更正简单的不规范代码
          cache: true	//开启构建缓存,第二次构建时更快
        }
      }]
    }]
  }
}

打包ts文件

ts-loader将typescript文件编译成js文件,该loader依赖typescript编译环境,所以需要使用npm install typescript -D预先安装typescript

同时为项目配置一个tsconfig.json文件,来配置typescript环境

{
  "compilerOptions" : {	//配置编译环境选项
    "outDir": "./dist",	//编译后的输出目录,不配也行,因为webpack已经指定
    "module": "commonjs",	//使用commonjs的模块化,若使用es6模块化时与HtmlWebpackPlugin联用时会报错,因为HtmlWebpackPlugin使用的是commonjs模块化
    "target": "es5",	//将typescript编译成es5语法
    "allowJs": true,	//允许在typescript中引入js模块
    "sourceMap": true,	//开启sourceMap功能
  }
}

若在typescript中引入的js的库,需要一些类型提示时可使用npm install @types/库名 -D安装类型校验即可

使用ts-loader首先需要使用npm install ts-loader -D安装该loader,并编写以下规则(输出和模式采用默认了)

module.exports = {
  entry: "./index.ts",	//入口文件路径
  module: {
    rules: [{
      test: /\.(ts|tsx)$/,	//使用正则匹配到以ts或tsx结尾的文件
      exclude: /node_modules/,	//排除掉node_modules中第三方模块的文件
      loader: "ts-loader",	//使用ts-loader对js文件进行编译打包
    }]
  }
}
此作者没有提供个人介绍
最后更新于 2021-12-20