03-webpack核心基础-loader

什么是loader?


webapck的本质是一个模块打包工具, 所以webpack默认只能处理JS文件,不能处理其他文件,
因为其他文件中没有模块的概念, 但是在企业开发中我们除了需要对JS进行打包以外,
还有可能需要对图片/CSS等进行打包, 所以为了能够让webpack能够对其它的文件类型进行打包,
在打包之前就必须将其它类型文件转换为webpack能够识别处理的模块,
用于将其它类型文件转换为webpack能够识别处理模块的工具我们就称之为loader

如何使用loader


一般loader的使用方式分为三种:
1:在配置文件webpack.config.js中配置

module.exports = {
  // 单个 loader 的配置
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {}
          }
        ]
      }
    ]
  }
  // 多个 loader 的配置
  module: {
    rules: [
      {
        // 增加对 SCSS 文件的支持
        test: /\.scss/,
        // SCSS 文件的处理顺序为先 sass-loader 再 css-loader 再 style-loader
        use: [
          'style-loader',
          {
            loader:'css-loader',
            // 给 css-loader 传入配置项
            options:{
              minimize:true, 
            }
          },
          'sass-loader'],
      },
    ]
  }
}

2:通过命令行参数方式

webpack --module-bind 'txt=raw-loader'

3:通过内联使用

import txt from 'raw-loader!./file.txt';

webpack常用的loader


  • 样式:style-loader、css-loader、less-loader、sass-loader等
  • 文件:raw-loader、file-loader 、url-loader等
  • 编译:babel-loader、coffee-loader 、ts-loader等
  • 校验测试:mocha-loader、jshint-loader 、eslint-loader等

file-loader


中文文档

1. 安装file-loader
npm install --save-dev file-loader
2. 在webpack.config.js中配置file-loader

webpack.config.js

module.exports = {
  // module: 告诉webpack如何处理webpack不能够识别的文件
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {}
          }
        ]
      }
    ]
  }
}
3. 其他配置(options)
  1. 默认情况下fileloader生成的图片名就是文件内容的 MD5 哈希值
    如何想打包后不修改图片的名称, 那么可以新增配置 name: "[name].[ext]"
    其它命名规则详见: placeholders

  2. 默认情况下fileloader会将生成的图片放到dist根目录下面
    如果想打包之后放到指定目录下面, 那么可以新增配置 outputPath: "images/"

  3. 如果需要将图片托管到其它服务器, 那么只需在打包之前配置 publicPath: "托管服务器地址"即可

例如:

module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: "[name].[ext]",
                            outputPath: "images/",
                            publicPath: "http://www.baidu.com/images/"
                        }
                    }
                ]
            }
        ]
    }

url-loader


中文文档
url-loader 功能类似于 file-loader,
但是在文件大小(单位 byte)低于指定的限制时,可以返回一个 DataURL

1. 安装urlloader
npm install --save-dev url-loader
2. 配置urlloader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              // limit: 指定图片限制的大小
              limit: 1024*100,
              // 指定打包后的文件名称
              name: "[name].[ext]",
              // 指定打包后文件存放目录
              outputPath: "images/"
            }
          }
        ]
      }
    ]
  }
}

【注意】
如果被打包的图片超过了限制的大小, 就会将图片保存为一个文件
如果被打包的图片没有超过限制的大小, 就会将图片转换成base64的字符串

对于比较小的图片, 我们将图片转换成base64的字符串之后, 可以提升网页的性能(因为减少了请求的次数)
对于比较大的图片, 哪怕我们将图片转换成了base64的字符串之后, 也不会提升网页的性能, 还有可能降低网页的性能(因为图片如果比较大, 那么转换之后的字符串也会比较多, 那么网页的体积就会变大, 那么访问的速度就会变慢)

优势:
图片比较小的时候直接转换成base64字符串图片, 减少请求次数
图片比较大的时候由于生成的base64字符串图片也比较大, 就保持原有的图片

html-withimg-loader


我们通过file-loader或者url-loader已经可以将JS或者CSS中用到的图片打包到指定目录中了
但是file-loader或者url-loader并不能将HTML中用到的图片打包到指定目录中
所以此时我们就需要再借助一个名称叫做"html-withimg-loader"的加载器来实现HTML中图片的打包
参考文档

1. 安装html-withimg-loader
npm install html-withimg-loader --save
2. 配置html-withimg-loader

webpack.config.js

{
    test: /\.(htm|html)$/i,
    loader: 'html-withimg-loader'
}

image-webpack-loader 和 img-loader(压缩图片)


在开发中为了提升网页的访问速度, 我们除了会压缩HTML/CSS/JS以外,还会对网页上的图片进行压缩, 压缩可以减少网页体积。
image-webpack-loader 和 img-loader都可以压缩打包之后的图片, 这里我们选择image-webpack-loader 演示
参考文档: image-webpack-loaderimg-loader

1. 安装image-webpack-loader
npm install image-webpack-loader --save-dev
2. 配置image-webpack-loader

webpack.config.js

rules: [{
  test: /\.(gif|png|jpe?g|svg)$/i,
  use: [
    'file-loader',
    {
      loader: 'image-webpack-loader',
      options: {
        mozjpeg: {
          progressive: true,
          quality: 65
        },
        // optipng.enabled: false will disable optipng
        optipng: {
          enabled: false,
        },
        pngquant: {
          quality: [0.65, 0.90],
          speed: 4
        },
        gifsicle: {
          interlaced: false,
        },
        // the webp option will enable WEBP
        webp: {
          quality: 75
        }
      }
    },
  ],
}]

postcss-sprites和webpack-spritesmith(合并图片)


过去为了减少网页请求的次数, 我们需要"UI设计师"给我们提供精灵图, 并且在使用时还需要手动的去设置每张图片的位置。但是有了webpack之后我们只需要让"UI设计师"给我们提供切割好的图片,我们可以自己合成精灵图, 并且还不用手动去设置图片的位置
postcss-sprites和webpack-spritesmith都可以合并图片, 这里只介绍postcss-sprites
参考文档: postcss-spriteswebpack-spritesmith

1. 安装postcss-sprites
npm install --save-dev postcss
npm install --save-dev postcss-sprites
2. 配置postcss-sprites

postcss.config.js

module.exports = {
    plugins: {
        "postcss-sprites": {
            // 告诉webpack合并之后的图片保存到什么地方
            spritePath: "./bundle/images",
            // 告诉webpack合并图片的时候如何分组
            groupBy: function (image) {
                let path = image.url.substr(0, image.url.lastIndexOf('/'));
                let name = path.substr(path.lastIndexOf("/") + 1);
                return  Promise.resolve(name);
            },
            // 告诉webpack哪些图片需要合并, 哪些图片不需要合并
            filterBy: function (image) {
                let path = image.url;
                // 如果不是以png结尾的图片就不合并
                // 这里的过滤规则可以自定义
                if (!/\.png$/.test(path)){
                    return Promise.reject();
                } 
                // 如果是以png结尾的图片就合并
                return Promise.resolve();
            } 
        }
    }
};

iconfot-loader(打包字体图标)


如何打包字体图标

字体图标中也用到了url用到了文件, 所以我们需要通过file-loader来处理字体图标文件
webpack.config.js

{
    test: /\.(eot|svg|ttf|woff|woff2)$/,
    use:[{
        loader: "file-loader",
        options: {
            name: "[name].[ext]",
            outputPath: "font/",
        }
    }]
}

css-loader


和图片一样webpack默认能不能处理CSS文件, 所以也需要借助loader将CSS文件转换为webpack能够处理的类型

1. 安装css-oader
npm install --save-dev css-loader
2. 安装style-loader
npm install style-loader --save-dev
3. 配置css-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [ 'style-loader', 'css-loader' ]
      }
    ]
  }
}

css-loader和style-loader作用

css-loader: 解析css文件中的@import依赖关系
style-loader: 将webpack处理之后的内容插入到HTML的HEAD代码中

css-loader模块化


默认情况下通过import "./xxx.css"导入的样式是全局样式, 也就是只要被导入, 在其它文件中也可以使用。如果想要导入的CSS文件只在导入的文件中有效, 那么就需要开启CSS模块化

目的:局部组件引入局部css样式,实现css模块化开发; 减免全局污染

操作
  • 启用css modules
    webpack.config.js
{
    loader: "css-loader",
    options: {
        modules: true // 开启CSS模块化
    }
}
  • 使用css modules
    导入的地方通过 import xxx from "./xxx.css"导入
    在使用的地方通过 xxx.className方式使用即可, "xxx"是一个对象
    例如:
import cssModule from "./index.css";

oImg.setAttribute("class", cssModule.size);

less-loader


将Less文件转换为webpack能够处理的类型

1. 安装less-loader
npm install --save-dev less-loader less
2. 配置less-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [ 'style-loader', 'css-loader' , 'less-loader']
      }
    ]
  }
}

sass-loader


将SASS/SCSS文件转换为webpack能够处理的类型

1. 安装sass-loader
npm install sass-loader node-sass webpack --save-dev

如果安装的时候报错, 可以尝试执行nrm use cnpm将npm源改为cnpm

2. 配置sass-loader

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.(sass|scss)$/,
        use: [ 'style-loader', 'css-loader' , 'sass-loader']
      }
    ]
  }
}

postcss-loader


1. 什么是PostCSS?

官网
PostCSS 是目前流行的一个对 CSS 进行处理的工具。
PostCSS和sass/less不同, 它不是CSS预处理器, 它是一款使用插件去转换CSS的工具,它负责进一步处理 CSS 文件,比如自动补全浏览器前缀,自动把px代为转换成rem 等。

PostCSS有许多非常好用的插件, PostCSS 依托其强大的插件体系为 CSS 处理增加了无穷的可能性。

2. autoprefixer(自动补全浏览器前缀)
  • 安装postcss-loader
npm i -D postcss-loader
  • 安装autoprefixer插件
npm i -D autoprefixer
  • 配置postcss-loader
    在css-loader or less-loader or sass-loader之后添加postcss-loader
    webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
        ]
      }
    ]
  }
}
  • 创建并配置postcss-loader配置文件
    postcss.config.js
module.exports = {
    plugins: {
        "autoprefixer": {
            "overrideBrowserslist": [
                "ie >= 8", // 兼容IE7以上浏览器
                "Firefox >= 3.5", // 兼容火狐版本号大于3.5浏览器
                "chrome  >= 35", // 兼容谷歌版本号大于35浏览器,
                "opera >= 11.5", // 兼容欧朋版本号大于11.5浏览器,
            ]
        }
    }
};
3. postcss-pxtorem(自动把px代为转换成rem)
  • 安装postcss-loader
npm i -D postcss-loader
  • 安装postcss-pxtorem
npm install postcss-pxtorem -D
  • 在配置文件中配置postcss-pxtorem
    postcss.config.js
module.exports = {
    plugins: {
        "postcss-pxtorem": {
            rootValue: 100, // 根元素字体大小
            // propList: ["*"]   // 可以从px更改到rem的属性
            propList: ["height"]   
        }
    }
};

postcss-pxtorem常用参数配置:

  • rootValue (Number) root 元素的字体大小。
  • unitPrecision (Number) 允许REM单位增长到的十进制数。
  • propList ( array ) 可以从px更改到rem的属性。
    值需要精确匹配。
    使用通配符 * 启用所有属性。 示例:[ ' * ' ]
    在单词的开头或者结尾使用 。 ( [ ' position ' ] 将匹配 background-position-y )
    使用 与属性不匹配。! 示例:[' letter-spacing ']!
    将"非"前缀与其他前缀合并。 示例:['
    ', 'font*']!
  • selectorBlackList ( array ) 要忽略和离开的选择器。
    如果值为字符串,它将检查选择器是否包含字符串。
    ['body'] 将匹配 .body-class
    如果值为 regexp,它将检查选择器是否匹配正则表达式。
    [/^body$/] 将匹配 body,但不匹配 .body
  • replace (Boolean) 替代包含rems的规则,而不是添加回退。
  • mediaQuery (Boolean) 允许在媒体查询中转换 px。
  • minPixelValue (Number) 设置要替换的最小像素值。

eslint


ESLint 是一个插件化的 javascript 代码检测工具,它可以用于检查常见的 JavaScript 代码错误,也可以进行"代码规范"检查,在开发中项目负责人会定制一套 ESLint 规则,然后应用到所编写的项目上,从而实现辅助编码规范的执行,有效控制项目代码的质量。在编译打包时如果语法有错或者有不符合规范的语法就会报错, 并且会提示相关错误信息
参考文档: eslint-loadereslint中文文档

  • 安装对应环境和loader
npm install eslint --save-dev
npm install eslint-loader --save-dev
  • 配置文件
    webpack.config.js
module.exports = {
  // ...
  module: {
    rules: [
      // 检查编码规范的规则
      {
        test: /\.js$/,
        // 让当前的loader在其他loader之前执行
        enforce: pre,
        // 过滤 node_modules 文件夹
        exclude: /node_modules/,
        // 只检查src目录
        include: path.resolve(__dirname, "src"),
        loader: 'eslint-loader',
        options: {
          // 检查代码时发现不符合规范的代码会自动修复
          fix: true
        },
      },
    ],
  },
  // ...
};
module.exports = {
  /*
  不重要,永远写true
  * */
  root: true,
  parserOptions: {
    // parser: 'babel-eslint',
    /*
    默认设置为 3,5(默认), 你可以使用 6、7、8、9 或 10 来指定你想要使用的 ECMAScript 版本
    * */
    "ecmaVersion": 10,
    /*
    设置为 "script" (默认) 或 "module"(如果你的代码是 ECMAScript 模块)。
    * */
    "sourceType": "module",
    /*
    ecmaFeatures - 这是个对象,表示你想使用的额外的语言特性:
    globalReturn - 允许在全局作用域下使用 return 语句
    impliedStrict - 启用全局 strict mode (如果 ecmaVersion 是 5 或更高)
    jsx - 启用 JSX
    * */
    "ecmaFeatures": {}
  },
  // 指定代码运行的宿主环境
  env: {
    browser: true, // 浏览器
    node: true, // node
    /*
    支持 ES6 语法并不意味着同时支持新的 ES6 全局变量或类型(比如 Set 等新类型)。
    对于 ES6 语法,使用 { "parserOptions": { "ecmaVersion": 6 } }
    * */
    es6: true,
  },
  extends: [
      /*
      引入standard代码规范
      * */
    // https://github.com/standard/standard/blob/master/docs/README-zhcn.md
    'standard'
  ],
  /*
  扩展或覆盖规则
  * */
  rules: {
    // 强制语句结束添加,分号
    semi: ["error", "always"],
    // 强制缩进2个空格
    indent: ["error", 4],
    // 方法名和刮号之间不加空格
    'space-before-function-paren': ['error', 'never'],
    "no-unexpected-multiline": "off"
  }
};

如果要使用standard代码规范, 还必须安装它

npm install standard --save-dev
  • 如何自动修复不符合规范的代码
  1. webpack.config.js配置文件的规则中新增fix: true
options: {
    // 检查代码时发现不符合规范的代码会自动修复
    fix: true
},

弊端: 只能在打包的时候自动修复

  1. 借助webstorm
    可以在编写代码的时候修复不符合规范的代码
    在webstorm的sitting中搜索eslint, 选中手动配置



    选中自己编写的规则



    发现自己在编写代码的时候出现了红线提示, 可以右键鼠标选择最后一个, 就会自动修改不符合规则的代码

loader特点:


1. 单一原则, 一个loader只做一件事情
2. 多个loader会按照从右至左, 从下至上的顺序执行

例如: 从右至左

      [ 'style-loader', 'css-loader' ]

先执行css-loader解析css文件关系拿到所有内容,
再执行style-loader将内容插入到HTML的HEAD代码中

例如: 从下至上

    [{
        loader: "style-loader"
    },{
        loader: "css-loader"
    }]

先执行css-loader解析css文件关系拿到所有内容,
再执行style-loader将内容插入到HTML的HEAD代码中

如果一个源文件需要经历多步转换才能正常使用,就通过多个 Loader 去转换。
在调用多个 Loader 去转换一个文件时,每个 Loader 会链式的顺序执行,
第一个 Loader 将会拿到需处理的原内容,上一个 Loader 处理后的结果会传给下一个接着处理,最后的 Loader 将处理后的最终结果返回给 Webpack。
所以,在你开发一个 Loader 时,请保持其职责的单一性,你只需关心输入和输出。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容