概要

webpack可以解决不同类型的文件进行一个加载打包过程,核心原理就是webpck的Loader。Webpack 是用 Loader(加载器)来处理每个模块的,而内部默认的 Loader 只能处理 JS 模块,如果需要加载其他类型的模块就需要配置不同的 Loader。
image.png

举例,解析 Css

安装

  1. $ npm install css-loader style-loader --save-dev
  2. # or yarn add css-loader style-loader --dev

配置

  1. // ./src/webpack.config.js
  2. module.exports = {
  3. entry: './src/main.css',
  4. output: {
  5. filename: 'bundle.js'
  6. },
  7. module: {
  8. rules: [
  9. {
  10. test: /\.css$/,
  11. // 对同一个模块使用多个 loader,注意顺序
  12. use: [
  13. 'style-loader',
  14. 'css-loader'
  15. ]
  16. }
  17. ]
  18. }
  19. }

流程

image.png

为什么要在 JS 中加载其他资源

一般情况 webpack 的打包入口都是 Js,为什么有这样的设置了?从某种意义来说,打包入口就是运用程序的入口,在当前前端来说,都是以 Js 为业务驱动的。所以把 Js 当做入口是比合理的。然后在 Js 中去加载其他的资源文件。

通过 JavaScript 代码去引入资源文件,或者说是建立 JavaScript 和资源文件的依赖关系,具有明显的优势。因为 JavaScript 代码本身负责完成整个应用的业务功能,放大来说就是驱动了整个前端应用,而 JavaScript 代码在实现业务功能的过程中需要用到样式、图片等资源文件。如果建立这种依赖关系:

  • 一来逻辑上比较合理,因为 JS 确实需要这些资源文件配合才能实现整体功能;
  • 二来配合 Webpack 这类工具的打包,能确保在上线时,资源不会缺失,而且都是必要的。

Loader

loader 是文件加载器,能够加载资源文件,一个 loader 只能处理一件事情,保证简单可维护,复杂的场景可能用多个 loader 组合完成。loader 可以对文件进行处理,最后打包到指定的文件中。

  • 处理一个文件可以使用多个loader,loader的执行顺序和配置中的顺序是相反的,即最后一个loader最先执行,第一个loader最后执行。
  • 第一个执行的loader接收源文件内容作为参数,其它loader接收前一个执行的loader的返回值作为参数,最后执行的loader会返回此模块的JavaScript源码。
  • 同步 loader 和 异步 loader
  • Loader 就是负责完成项目中各种各样资源模块的加载,从而实现整体项目的模块化

image.png

开发一个 Loader

注意1:如果是最后一个loader需要返回一段js代码字符串 注意2:js代码字符串不能直接返回,直接返回将无法解析,需要使用commonjs或者ES module模糊化语法导出。 注意3:多个 loader 配置使用,后一个 loader 的接受参数是前一个参数的返回。

  1. // ./markdown-loader.js
  2. const marked = require('marked')
  3. module.exports = source => {
  4. // 1. 将 markdown 转换为 html 字符串
  5. const html = marked(source)
  6. // html => '<h1>About</h1><p>this is a markdown file.</p>'
  7. // 2. 将 html 字符串拼接为一段导出字符串的 JS 代码
  8. // const code = `module.exports = ${JSON.stringify(html)}`
  9. const code = `export default ${JSON.stringify(html)}`
  10. return code
  11. // code => 'export default "<h1>About</h1><p>this is a markdown file.</p>"'
  12. }
  1. // ./webpack.config.js
  2. module.exports = {
  3. entry: './src/main.js',
  4. output: {
  5. filename: 'bundle.js'
  6. },
  7. module: {
  8. rules: [
  9. {
  10. test: /\.md$/,
  11. // 直接使用相对路径
  12. use: './markdown-loader'
  13. }
  14. ]
  15. }
  16. }