03webpack之常用loader转换器

发布时间 2023-10-09 17:35:51作者: songxia777

1 简介

loader 用于对模块的源代码进行转换

loader 可以使你在 import 或"加载"模块时预处理文件

因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法

loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS文件!

1.1 使用loader

在应用程序中,有三种使用 loader 的方式:

1、 在 webpack.config.js 文件中指定 loader(推荐)

2、 在每个 import 语句中显式指定 loader

3、 在 shell 命令中指定它们。

1.1.1 配置

module.rules 允许在 webpack 配置中指定多个 loader。 这种方式是展示 loader 的一种简明方式,并且有助于使代码变得简洁和易于维护。同时让你对各个 loader 有个全局概览:

loader 是从右到左地取值(evaluate)/执行(execute)

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

1.1.2 内联

可以在 import 语句或 任何等同于 "import" 的方法 中指定 loader。使用 ! 将资源中的 loader 分开。每个部分都会相对于当前目录解析

import Styles from 'style-loader!css-loader?modules!./styles.css';

1.1.3 脚手架 cli

还可以通过 CLI 使用 loader

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

1.2 loader特性

  • loader 支持链式传递。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 期望 JavaScript。
  • loader 可以是同步的,也可以是异步的。
  • loader 运行在 Node.js 中,并且能够执行任何 Node.js 能做到的操作。
  • loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
  • 除了常见的通过 package.jsonmain 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
  • 插件(plugin)可以为 loader 带来更多特性。
  • loader 能够产生额外的任意文件。

1.3 解析loader

loader 遵循 模块解析 标准。多数情况下,loader 将从 模块路径 加载(通常是从 npm install, node_modules 进行加载)。

通常使用 npm 进行管理,但是也可以将自定义 loader 作为应用程序中的文件。按照约定,loader 通常被命名为 xxx-loader(例如 json-loader

2 打包样式资源 (css scss less 等)

2.1 安装依赖

# 处理css文件
npm i -D css-loader style-loader 

# 处理 sass文件
npm i -D sass sass-loader 

# 处理 less 文件
npm i -D less less-loader

2.2 webpack.config.js 配置

/*
webpack.config.js  webpack的配置文件
作用: 指示 webpack 干哪些活(当你运行 webpack 指令时,会加载里面的配置)

所有构建工具都是基于nodejs平台运行的,模块化默认采用commonjs
*/

// 引入node的path处理对象
// resolve用来 拼接绝对路径
const { resolve } = require('path');

module.exports = {
  // 入口起点
  entry: './src/index.js',

  // 输出
  output: {
    // 输出文件名
    filename: 'build.js',
    // 输出路径
    // __dirname nodejs的变量,代表当前文件的目录绝对路径
    path: resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      // 配置编译css文件的loader
      {
        // 匹配文件
        test: /\.css$/,

        /* 使用哪些loader处理
           use数组中loader的执行顺序:从右到左,从下到上 依次执行
           style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效
           css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串
        */
        use: ['style-loader', 'css-loader']
      },
      // 配置编译sass 或 scss 文件的loader
      {
        test: /\.s[a|c]ss$/i,
        // 需要下载 sass sass-loader 依赖
        use: [
          'style-loader',
          'css-loader',
          // 可以将 *.scss文件编译为*.css
          'sass-loader'
        ]
      }
    ]
  },
  // 开发模式:默认是 生产环境开发模式 production
  mode: 'development'
}

相关介绍:

1、 const { resolve } = require('path'); resolve 是node中用来处理 拼接绝对路径的path模块

2、style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效

3、 css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串

4、sass-loader:可以编译处理sass样式文件

2.3 样式抽离

mini-css-extract-plugin 插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载

更多配置参考

2.3.1 安装依赖

npm i -D mini-css-extract-plugin

2.3.2 webpack.config.js配置

const { resolve } = require('path');

// 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
        test: /\.s[a|c]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'css/[name].[contenthash:5].css'
    })
  ],
  mode: 'development'
}

2.4 CSS 兼容性处理 postcss

2.4.1 安装依赖

npm install --save-dev postcss-loader postcss postcss-preset-env

2.4.2 webpack.config.js 配置

const { resolve } = require('path');

// 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env'
                ]
              }
            }
          }
        ]
      },
      {
        test: /\.s[a|c]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env'
                ]
              }
            }
          },
          'sass-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'build.css'
    })
  ],
  mode: 'development'
}

更多配置参考

2.5 压缩css

2.5.1 安装依赖

npm install css-minimizer-webpack-plugin --save-dev

2.5.2 webpack.config.js 配置

const { resolve } = require('path');

// 本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

// 压缩css
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env'
                ]
              }
            }
          }
        ]
      },
      {
        test: /\.s[a|c]ss$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  'postcss-preset-env'
                ]
              }
            }
          },
          'sass-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new MiniCssExtractPlugin({
      // 对输出的css文件进行重命名
      filename: 'build.css'
    })
  ],
  // 压缩css  
  optimization: {
    // 默认是只在生产环境下 压缩,如果要在开发环境下压缩,需要开启optimization.minimize为true 
    minimize: true,
    minimizer: [
      new CssMinimizerPlugin(),
    ],
  },
  mode: 'development'
}

3 打包html资源 html-webpack-plugin

3.1 主要作用

1、 动态生成html文件,并自动引入打包输出的所有资源(JS/CSS)

2、 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置Nhtml-webpack-plugin可以生成N个页面入口

3、 静态文件无需加载js或css文件,通过设置入口文件可以将js文件自动添加进去,而相关的css文件在js中导入

4、 同时修改生成的js文件命名规则,利用hash码命名js文件

5、 没有改动时可以让浏览器缓存内容,当有改动重新部署后可以让浏览器缓存失效

6、 为html文件中引入的外部资源如scriptlink动态添加每次compile后的hash,防止引用缓存的外部文件问题

原理:

将 webpack中entry配置的相关入口chunk 和 extract-text-webpack-plugin抽取的css样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个html文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body

3.2 安装依赖

npm i -D html-webpack-plugin

3.3 webpack.config.js 配置

const { resolve } = require('path');

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'dist'),
      // 打包前清理 dist 文件夹
    clean: true
  },
  plugins: [
    // 功能:默认会创建一个空的HTML,并自动引入打包输出的所有资源(JS/CSS)
    new HtmlWebpackPlugin({
      // 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html',
      // 打包生成的文件名称。默认为index.htmls
      filename: 'app.html',
      title: 'webpack html插件',
      hash: true,
      // 设置所有资源文件注入模板的位置。可以设置的值  true|'head'|'body'|false,默认值为 true
      inject: 'body'
    })
  ],
  mode: 'development'
}

不配置任何选项的html-webpack-plugin插件,他会默认将webpack中的entry配置所有入口thunk和extract-text-webpack-plugin抽取的css样式都插入到文件指定的位置

清理dist

清理dist 仔细留意一下,我们发现 dist/index.html 仍旧存在,这个文件是上次生成的残留 文件,已经没有用了。可见,webpack 将生成文件并放置在 /dist 文件夹中,但是 它不会追踪哪些文件是实际在项目中用到的。通常比较推荐的做法是,在每次构建前 清理 /dist 文件夹,这样只会生成用到的文件

3.4 插件常用参数

title

打包生成的html文档的标题

配置该项,它并不会替换指定模板文件中的title元素的内容,除非html模板文件中使用了模板引擎语法来获取该配置项值

<title>{%= o.htmlWebpackPlugin.options.title %}</title>

template:模板文件路径

指定你生成的文件所依赖的是哪一个html文件模板,模板类型可以是html、jade、ejs等

但是要注意的是,如果想使用自定义的模板文件的时候,你需要安装对应的loader

为template指定的模板文件没有指定任何loader的话,默认使用ejs-loader。如template: './index.html',若没有为.html指定任何loader就使用ejs-loader

filename:文件名称

输出文件的文件名称,默认为index.html,还可以为输出文件指定目录位置(例如'html/index.html'),一般是相对路径

filename配置的html文件目录是相对于webpackConfig.output.path路径而言的,不是相对于当前项目目录结构的

指定生成的html文件内容中的link和script路径是相对于生成目录下的,写路径的时候一般是生成目录下的相对路径

templateContent

可以指定模板的内容,不能与template共存。配置值为function时,可以直接返回html字符串,也可以异步调用返回html字符串

inject

template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同

1、true或者body:所有JavaScript资源插入到body元素的底部

2、head: 所有JavaScript资源插入到head元素中

3、false: 所有静态资源css和JavaScript都不会注入到模板文件中

minify

传递 html-minifier 选项给 minify 输出,false就是不使用html压缩

具体参数请参考:html-minifier

minify: {
	collapseWhitespace: true, //打包后是否删除空格(压缩)
	removeAttributeQuotes: true // 移除属性的引号
},
  • caseSensitive(默认false):以区分大小写的方式处理属性(适用于定制的HTML标记)

  • collapseBooleanAttributes(默认false):从布尔属性中省略属性值

  • collapseInlineTagWhitespace Don't leave any spaces between display:inline;elements when collapsing. Must be used in conjunction with collapseWhitespace=true false

  • collapseWhitespace 在显示之间不要留下任何空格:内联;崩溃时的元素。必须与折叠空间结合使用=true ? false

  • conservativeCollapse 总是折叠到1个空间(永远不要完全删除它)。必须与折叠空间结合使用=true ? false

  • customAttrAssign 允许支持自定义属性分配表达式的正则表达式数组。 (e.g. '<div flex?="{{mode != cover}}">') [ ]

  • customAttrCollapse Regex指定自定义属性以从(例如/ng-class/)删除新行。

  • customAttrSurround 允许支持自定义属性包围表达式的正则表达式数组(e.g. <input {{#if value}}checked="checked"{{/if}}>) [ ]

  • customEventAttributes 允许为minifyJS支持自定义事件属性的正则表达式数组(例如,ng-click) [ /^on[a-z]{3,}$/ ]

  • decodeEntities 尽可能使用直接的Unicode字符。false

  • html5 根据HTML5规范分析输入。 true

  • ignoreCustomComments 当匹配时,允许忽略某些注释的正则表达式数组。 [ /^!/ ]

  • ignoreCustomFragments 当匹配时,允许忽略某些片段的正则表达式数组(例如,{ {…} },等等)。 [ /<%[\s\S]?%>/, /<?[\s\S]??>/ ]

  • includeAutoGeneratedTags 插入由HTML解析器生成的标记。 true

  • keepClosingSlash 保留单例元素的末尾斜杠。 false

  • maxLineLength 指定最大行长度。压缩的输出将在有效的HTML分割点上被换行。

  • minifyCSS 缩小CSS样式元素和样式属性(usesclean-css) false (could betrue, Object,Function(text))

  • minifyJS 在脚本元素和事件属性中缩小JavaScript(使用UglifyJS) false (could betrue, Object,Function(text, inline))

  • minifyURLs 在各种属性中缩小url(使用relateurl) false (could beString, Object,Function(text))

  • preserveLineBreaks 当标记之间的空格包括换行符时,总是崩溃到1行中断(永远不要完全删除)。必须与折叠空间结合使用=true ? false

  • preventAttributesEscaping 防止属性值的溢出。 false

  • processConditionalComments 通过minifier处理条件评论的内容。 false

  • processScripts 通过minifier(例如text/ng-template、text/x-handlebars-template等)来处理脚本元素类型的字符串数组。 [ ]

  • quoteCharacter 用于属性值的引用类型('or')

  • removeAttributeQuotes 在可能的情况下删除引号。 false

  • removeComments 带HTML注释 false

  • removeEmptyAttributes 删除所有的属性,只有whitespace-only的值。 false (could betrue,Function(attrName, tag))

  • removeEmptyElements 删除所有含有空内容的元素。 false

  • removeOptionalTags 删除可选的标记 false

  • removeRedundantAttributes 当值匹配默认值时删除属性。 false

  • removeScriptTypeAttributes 从脚本标签中删除type="text/javascript"。其他类型的属性值是完整的。false

  • removeStyleLinkTypeAttributes 从style和link标签中删除type="text/css"。其他类型的属性值是完整的。 false

  • removeTagWhitespace 尽可能在属性之间移除空间。注意,这将导致无效的HTML! false

  • sortAttributes 根据频率属性进行排序 false

  • sortClassName 按频率分类样式类。 false

  • trimCustomFragments 在ignoreCustomFragments周围调整空白区域。 false

  • useShortDoctype 用short (HTML5) doctype替换doctype。 false

chunks

1、 允许插入到模板中的一些chunk,不配置此项默认会将entry中所有的thunk注入到模板中

2、 在配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk

chunks主要是将你选择的资源注入到模板中

plugins: [
    new httpWebpackPlugin({
       chunks: ['index','main']
    })
]

那么编译后:

<script type=text/javascript src="index.js"></script>
<script type=text/javascript src="main.js"></script>

excludeChunks

这个与chunks配置项正好相反,排除掉一些js,用来配置不允许注入的thunk

chunksSortMode

允许指定的thunk在插入到html文档前进行排序,默认是auto,可选值:none | auto| function

  • auto基于thunk的id进行排序
  • function值可以指定具体排序规则
  • none就是不排序

favicon

添加特定 favicon 路径到输出的html文档中,这个同title配置项,需要在模板中动态获取其路径值

结果是将生成的html文件生成一个 favicon ,值是一个路径 :favicon: 'path/to/my_favicon.ico',然后再生成的html中就有了一个 link 标签

<link rel="shortcut icon" href="example.ico">

cache:true|fasle, 默认true

表示内容变化的时候生成一个新的文件

如果为true表示在对应的thunk文件修改后就会emit文件

hash

是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值,添加hash形式如下所示:

html <script type="text/javascript" src="common.js?a3e1396b501cdd9041be"></script>

xhtml

是否渲染link为自闭合的标签(默认false),true则为自闭合标签

showErrors

是否将错误信息输出到html页面中,默认true

3.5 配置多个html页面例子

应用中配置了三个入口页面:index.html、course.html、about.html;并且每个页面注入的thunk不尽相同;

类似如果多页面应用,就需要为每个页面配置一个;

// 需要暴露在全局(模块的导出)
// __dirname目录就是E:\MyLocalProject\webpackDemo
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: {
    general: './src/skin/general/js/general.js',
    index: './src/skin/index/js/index.js',
    course: './src/skin/course/js/index.js',
    about: './src/skin/about/js/index.js',
},
output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'skin/[name]/[name].js',  //必须是相对路径
    publicPath: '../../'
},
module: {
    rules: [
        //配置babel,自动编译es6语法
        {
            test: /\.js$/,
            exclude: /(node_modules)/,
            loader: 'babel-loader'
        },

    ]
},
//插件的相关配置
plugins: [
    //配置html文件
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/index.html'),
        filename: 'static/index.html',
        minify: {
            collapseWhitespace: true
        },
        hash: true,
        favicon: 'favicon.ico',
        chunks: ['general', 'index']
    }),
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/course/index.html'),
        filename: 'static/course/index.html',
        minify: {
            collapseWhitespace: true,
        },
        hash: true,
        favicon: 'favicon.ico',
        chunks: ['general', 'course']
    }),
    new htmlWebpackPlugin({
        template: path.join(__dirname, '/src/static/about/index.html'),
        filename: 'static/about/index.html',
        minify: {
            collapseWhitespace: true
        },
        hash: true,
        chunks: ['general', 'about'],
        favicon: 'favicon.ico'
    }),
]
}

使用glob 扫描路径,自动配置html

    // __dirname目录就是E:\MyLocalProject\webpackDemo
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')

//扫描入口目录static的路径
const glob = require("glob");
const staticHtmlPath = glob.sync('src/static/**/*.html');

//定义入口对象entrys
const entrys = {};
//设置公共的js入口文件
const commonJSObj = {
  general: './src/skin/general/js/general.js',
}
Object.assign(entrys, commonJSObj)

//定义html-webpack-plugin配置项
const htmlCfgs = [];
const htmlCfgsObj = {};
staticHtmlPath.forEach((filePath) => {
  let path = filePath.split('/')
  let pathLength = path.length
  //获取文件名
  let filename = path[pathLength - 1].split('.')[0]

  //动态配置入口文件路径
  let entryJSName = path[pathLength - 2] + '-' + filename
  entrys[entryJSName] = './src/skin/' + path[pathLength - 2] + '/js/' + filename + '.js';
  htmlCfgs.push( //动态配置入口文件插件
    new htmlWebpackPlugin({
      template: filePath,
      filename: filePath.replace('src', ''),
      minify: {
        collapseWhitespace: true
      },
      hash: true,
      favicon: 'favicon.ico',
      chunks: [entryJSName, 'general'],
    })
  )
});

module.exports = {
  devtool: 'inline-source-map',
  // 入口
  entry: entrys,
  // 出口
  output: {
    path: path.resolve(__dirname, 'dist'), //必须是绝对路径
    filename: 'skin/[name]/[name].js',  //必须是相对路径
    publicPath: '../../'
  },
  // 开发服务器
  devServer: {},
  // 模块配置
  module: {
    rules: [
      //配置babel,自动编译es6语法
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader'
      },
    ]
  },
  //插件配置
  plugins: htmlCfgs,
  //配置解析
  resolve: {}
}

参考文章:
https://www.cnblogs.com/wonyun/p/6030090.html

4 资源模块 asset moudle

4.1 概述

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader

在 webpack 5 之前,通常使用:

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

1、 asset/resource 发送一个单独的文件并导出 URL。webpack4是通过使用 file-loader 实现

2、 asset/inline 导出一个资源的 data URI (base64图)。之前通过使用 url-loader 实现

3、 asset/source 导出资源的源代码。之前通过使用 raw-loader 实现

4、 asset 在导出一个 data URI 和发送一个单独的文件之间自动选择(即在asset/inline 和 asset/resource之间自动选择)。之前通过使用 url-loader,并且配置资源体积限制实现

注意事项:

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

webpack.config.js设置

module.exports = {
  module: {
   rules: [
      {
        test: /\.(png|jpg|gif)$/i,
        // 如需从 asset loader 中排除来自新 URL 处理的 asset,请添加 dependency: { not: ['url'] } 到 loader 配置中
        dependency: { not: ['url'] },
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
            }
          },
        ],
       // 新增设置
       type: 'javascript/auto'
      },
   ]
  },
}

4.2 webpack.config.js配置

主要实现加载的资源模块有:图片(样式文件中的图片、html中的图片)、字体(例如iconfont)、文本、JSON等

const { resolve } = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build'),
    clean: true,
    // 设置 资源模块的打包输出路径 (优先级低于generator)
    assetModuleFilename: 'assets/images/[contenthash][ext]'
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      // 1.  资源模块:图片、svg等
      {
        test: /\.(png|jpg|gif|svg|jpeg)$/i,
        type: 'asset',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/images/[name][ext]'
          // filename: 'assets/images/[contenthash][ext]',
          // filename: 'assets/images/[hash][ext][query]'
        },
        parser: {
          dataUrlCondition: {
            // 如果 资源的大小 小于 8KB,就转换为 base64位图的方式
            maxSize: 8 * 1024
          }
        }
      },

      // 2.  处理html文件的img图片  html-withimg-loader
      {
        test: /\.html$/,
        loader: 'html-withimg-loader'
      },

      // 3.  资源模块:字体文件iconfont
      {
        test: /\.(svg|woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/[contenthash][ext]',
        }
      },

      // 4.  资源模块:*.txt *.json等文件
      {
        test: /\.(txt|json)$/i,
        type: 'asset/source',
        generator: {
          // 生成资源名称设置:以下3种都可以
          filename: 'assets/[contenthash][ext]',
        }
      },
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html',
      inject: 'body'
    })
  ],
  mode: 'development'
}

说明事项:

1、 处理 html 中的图片,需要加载一个 html-withimg-loader 这个loader处理

2、 设置生成资源的位置

generator: {
    // 生成资源名称设置:以下3种都可以
    filename: 'assets/images/[name][ext]'
    // filename: 'assets/images/[contenthash][ext]',
    // filename: 'assets/images/[hash][ext][query]'
},

3、图片资源限制设置

  parser: {
          dataUrlCondition: {
            // 如果 资源的大小 小于 8KB,就转换为 base64位图的方式
            maxSize: 8 * 1024
          }
        }

4.3 自定义json数据

资源模块可以 加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML等。

要导入 CSV、TSV 和 XML,你可以使用 csvloader 和 xml-loader

npm install --save-dev csv-loader xml-loader

添加配置

module: {
rules: [
    {
        test: /\.(csv|tsv)$/i,
        use: ['csv-loader'],
    },
    {
        test: /\.xml$/i,
        use: ['xml-loader'],
    },
  ]
}

通过使用 自定义 parser 替代特定的 webpack loader,可以将任何 toml 、 yaml 或 json5 文件作为 JSON 模块导入

npm install json5 --save-dev

添加配置

{
    test: /\.json5$/i,
    type: 'json',
    parser: {
        parse: json5.parse,
    },
},

5 打包图片资源

5.1 webpack5版本

5.1.1 安装依赖

# 处理html中的图片资源 html-withimg-loader w5版本
npm i -D html-withimg-loader

5.1.2 webpack.config.js配置

const { resolve } = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // 处理 css 样式文件
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      // 处理 scss 样式文件
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      // 处理 样式文件中的资源
      {
        test: /\.(png|jpg|gif)$/i,
        type: 'asset',
        generator: {
          filename: '[name].[hash:6][ext]'
        }
      },
      // 处理html文件的img图片,webpack5必须使用: html-withimg-loader
      {
        test: /\.html$/,
        loader: 'html-withimg-loader'
      }
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
}

5.2 webpack4版本

5.2.1 安装依赖

# 处理html中的图片资源 html-loader w4版本
npm i -D html-loader


# 处理样式文件中的资源 w4
npm i -D url-loader file-loader

5.2.2 webpack.config.js 配置

const { resolve } = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // 处理 css 样式文件
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      // 处理 scss 样式文件
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      // 处理 样式文件中的资源
      {
        test: /\.(png|jpg|gif)$/i,
        loader: 'url-loader',
        options: {
          // 图片大小小于8kb,就会被base64处理
          limit: 8 * 1024,
          // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
          // 解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          // 给图片进行重命名
          name: '[hash:10].[ext]'
        }
      },
      // 处理html文件的img图片
      {
        test: /\.html$/,
        loader: 'html-loader'
      }
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
}

image-webpack-loader 压缩图片

  1. webpack.config.js规则的配置

    /*
    * url-loader:主要是图片处理和Base64编码(base64就是一串加密的字符串,而且base64编码过的图片是没有http请求的)
    * image-webpack-loader:主要是压缩图片
    * /
    {
    test: /.(png|jpe?g|gif|svg)(?.
    )?$/,
    use: [
    {
    loader: "url-loader",
    options: {
    name: "[name]-[hash:5].min.[ext]",
    limit: 8192, // size <= 8KB
             publicPath: "../images",
    outputPath: "./images"
    }
    },
    {
    loader: 'image-webpack-loader',
    options: {
    bypassOnDebug: true
    }
    }
    ]
    },
    //主要是处理html中的img标签的loader
    {
    test: /.html$/,
    use: [{
    loader: 'html-loader',
    options: {
    minimize: true
    }
    }],
    }

5.3 打其他 资源:iconfont

5.3.1 webpack.config.js配置

const { resolve } = require('path');
const HtmlWbpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'build.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // 处理 css 样式文件
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      // 处理 scss 样式文件
      {
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      },
      {
        // 打包iconfont 转换文件格式
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        //文件打包方式
        type: "asset/resource",
        generator: {
          filename: `./assets/[contenthash][ext]`
        }
      },

      // 打包其他资源(除了html/js/css资源以外的资源)  webpack4 版本
      // {
      //   // 排除css/js/html资源
      //   exclude: /\.(css|js|html|scss)$/,
      //   loader: 'file-loader',
      //   options: {
      //     name: '[hash:10].[ext]',
      //     outputPath: 'media'
      //   }
      // }
    ]
  },
  plugins: [
    new HtmlWbpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'development'
}

5.3.2 index.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>Document</title>
</head>

<body>
  <span class="iconfont icon-dui"></span>
  <span class="iconfont icon-cha"></span>
</body>

</html>

5.3.3 index.js 入口文件

import './iconfont/iconfont.css'

5.4 合成雪碧图

雪碧图是为了减少网络请求,所以被处理雪碧图的图片多为各式各样的 logo 或者大小相等的小图片。而对于大图片,还是不推荐使用雪碧图。

5.1 安装依赖
//postcss-loader和postcss-sprites则用来合成雪碧图,减少网络请求
cnpm install --save-dev postcss-loader postcss-sprites
5.2 配置webpack.config.js文件
//配置雪碧图
let spritesConfig = {
    spritePath: "./dist/images"
};
5.3 结合postcss-loader配置postcss-sprites
// 编译css scss sass文件
        {
            test: /\.(sa|sc|c)ss$/,
            /*
            * 从右向左编译
            * style-loader:将 JS 字符串生成为 style 节点
            * css-loader:将 CSS 转化成 CommonJS 模块
            * sass-loader:// 将 Sass 编译成 CSS
            * use: ['style-loader', 'css-loader', "postcss-loader", 'sass-loader']
            * */
            use: [
                {
                    loader: "style-loader",
                    options: {
                        singleton: false // 处理为单个style标签
                    }
                },
                {
                    loader: "css-loader"
                },
                {
                    loader: 'postcss-loader',
                    //postcss-sprites需要结合postcss-loader合成雪碧图
                    options: {
                        ident: "postcss",
                        plugins: [require("postcss-sprites")(spritesConfig)]
                    }
                },
                {
                    loader: 'sass-loader'
                }
            ]

        },
        // 文本分离:配置scss
        {
            test: /\.scss$/,
            use: extractTextWebpackPlugin.extract({
                fallback: 'style-loader',
                use: [
                    {loader: 'css-loader'},
                    {
                        loader: 'postcss-loader',
                        //postcss-sprites需要结合postcss-loader合成雪碧区、图
                        options: {
                            ident: "postcss",
                            plugins: [require("postcss-sprites")(spritesConfig)]
                        }
                    },
                    {loader: 'sass-loader'}
                ]
            })
        },

6 webpack处理es6语法 babel-loader

6.1 安装依赖

# babel主要模块
npm i -D babel-loader @babel/core @babel/preset-env
 
# babel-loader: 在webpack里应用 babel 解析ES6的桥梁
# @babel/core:babel核心模块
# @babel/preset-env: : babel预设,一组 babel 插件的集合
# babel-plugin-transform-runtime: 避免 polyfill 污染全局变量

# regeneratorRuntime 是webpack打包生成的全局辅助函数,由babel生成,用于兼容async/await的语法
# 这个包中包含了regeneratorRuntime,运行时需要
npm install --save @babel/runtime

# 这个插件会在需要regeneratorRuntime的地方自动require导包,编译时需要
npm install --save-dev @babel/plugin-transform-runtime

6.2 webpack.config.js 配置

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: [
              [
                '@babel/plugin-transform-runtime',
                // '@babel/plugin-transform-arrow-functions'
                // '@babel/plugin-transform-object-assign'
              ]
            ]
          }
        }
      }
    ]
  },

6.3 创建babel配置文件 .babelrc 或者 babel.config.json

相关babale的配置也可以另外创建一个文件单独进行配置 (推荐)

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": "9", //这个是自己添加的,最好是加上
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "useBuiltIns": "usage", // 按需加载
        "corejs": 3
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-transform-runtime"
  ]
}

对应的 webpack.config.js 配置

module.exports = {
    module: {
        rules: [
            //配置babel,自动编译es6语法
            {
                test: /\.js$/,
                exclude: /(node_modules)/,
                loader: 'babel-loader'
            }
        ]
    },
}