Webpack 4(三)

Webpack 开发一个 Loader

开发一个 markdown-loader

// src/about.md
# 关于我

我是 robert, 一名技术爱好者~
import about from './about.md'
console.log(about)
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack - 开发一个 Loader</title>
</head>
<body>
  <script src="dist/bundle.js"></script>
</body>
</html>
yarn add html-loader@0.5.5 --dev
// ./markdown-loader.js
const marked = require('marked')

// Loader 负责资源文件从输入到输出的转换
// Loader 实际上是一种管道的概念
// 对于同一个资源可以依次使用多个 Loader

module.exports = source => {
  // console.log(source)
  // return 'console.log("hello ~")'
  const html = marked(source)
  // return html
  // return 'module.exports = "${html}"'
  // JSON.stringify 防止 html 中的换行符,内部引号拼接一起,造成错误
  // return `module.exports = ${JSON.stringify(html)}`
  // return `export default ${JSON.stringify(html)}`

  // 返回 html 字符串交个下一个 loader 处理
  return html
}
const path = require('path')

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /.md$/,
        use: [
          'html-loader',
          './markdown-loader'
        ]
      }
    ]
  }
}

Loader 工作原理

Loader 负责资源文件从输入到输出的转换,Loader 实际是一种管道的概念,可以将此次 Loader 的结果交给下一个 Loader 去处理,对于同一个资源可以依次使用多个 Loader。

管道工作后的结果必须是一段 JS 代码。

image

image

image

image

Webpack 插件机制介绍

插件可以增强 Webpack 自动化能力

  • 清除 dist 目录
  • 拷贝静态文件至输出目录
  • 压缩输出代码

自动清除输出目录插件

插件:clean-webpack-plugin

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack Plugins</title>
</head>
<body>
  <script src="dist/bundle.js"></script>
</body>
</html>
// ./package.json
{
  "name": "03-clean-webpack-plugin",
  "version": "0.1.0",
  "main": "index.js",
  "author": "",
  "license": "MIT",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "style-loader": "^1.0.0",
    "url-loader": "^2.2.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.9"
  }
}
// ./webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /.png$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10 * 1024 // 10 KB
          }
        }
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin()
  ]
}

image

自动生成 HTML 插件

通过硬编码的方式将 index.html 存放在项目根目录下,存在的问题:

  • 项目发布时,要同时发布 src/index.html 和 dist 目录下的打包结果,比较麻烦,同时还要确保 index.html 代码中的引用的 JS 等资源的路径是正确的
  • 打包的结果配置发生了变化,index.html 中 script 标签中引用的路径需要手动去修改

解决以上问题的办法:

通过 webpack 输出 HTML 文件,构建过程中 webpack 会自动将打包的 bundle 添加到页面中,HTML 也会输出到 dist 目录,bundle 是自动注入的,所以能确保路径的引用是正常的。

html-webpack-plugin

// package.json
{
  "name": "04-html-webpack-plugin",
  "version": "0.1.0",
  "main": "index.js",
  "author": "",
  "license": "MIT",
  "scripts": {
    "build": "webpack"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.2.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "style-loader": "^1.0.0",
    "url-loader": "^2.2.0",
    "webpack": "^4.40.2",
    "webpack-cli": "^3.3.9"
  }
}
// webpacck.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    // publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /.png$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10 * 1024 // 10 KB
          }
        }
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    // 用于生成 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Plugin Sample',
      meta: {
        viewport: 'width=device-width'
      },
      template: './src/index.html'
    }),
    // 用于生成 about.html
    new HtmlWebpackPlugin({
      filename: 'about.html'
    })
  ]
}
// src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Webpack</title>
</head>
<body>
  <div class="container">
    <h1><%= htmlWebpackPlugin.options.title %></h1>
  </div>
</body>
</html>

image

CopyWebpackPlugin

CopyWebpackPlugin 可将单个文件或整个目录复制到构建目录。

yarn add copy-webpack-plugin@5.0.4 --dev
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  mode: 'none',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.join(__dirname, 'dist'),
    // publicPath: 'dist/'
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader'
        ]
      },
      {
        test: /.png$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10 * 1024 // 10 KB
          }
        }
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    // 用于生成 index.html
    new HtmlWebpackPlugin({
      title: 'Webpack Plugin Sample',
      meta: {
        viewport: 'width=device-width'
      },
      template: './src/index.html'
    }),
    // 用于生成 about.html
    new HtmlWebpackPlugin({
      filename: 'about.html'
    }),
    new CopyWebpackPlugin([
      // 'public/**'
      'public'
    ])
  ]
}
posted @ 2022-09-02 15:00  小小紫苏  阅读(35)  评论(0)    收藏  举报