{"id":22897411,"url":"https://github.com/zzall/webpack-loader","last_synced_at":"2026-04-29T15:04:56.624Z","repository":{"id":129388531,"uuid":"497180192","full_name":"zzall/webpack-loader","owner":"zzall","description":"手动实现一个webpack-loader","archived":false,"fork":false,"pushed_at":"2022-05-31T14:20:40.000Z","size":11,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-06T05:34:40.345Z","etag":null,"topics":["javascript","webpack","webpack-loader"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zzall.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-28T01:14:13.000Z","updated_at":"2022-06-20T12:41:35.000Z","dependencies_parsed_at":"2023-04-05T00:24:29.127Z","dependency_job_id":null,"html_url":"https://github.com/zzall/webpack-loader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zzall/webpack-loader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzall%2Fwebpack-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzall%2Fwebpack-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzall%2Fwebpack-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzall%2Fwebpack-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zzall","download_url":"https://codeload.github.com/zzall/webpack-loader/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zzall%2Fwebpack-loader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32430805,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","webpack","webpack-loader"],"created_at":"2024-12-14T00:17:29.302Z","updated_at":"2026-04-29T15:04:56.590Z","avatar_url":"https://github.com/zzall.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"## 注意事项\n\n### 1、loader的本质\n\nloader的本质就是一个`module.exports`暴露出去的一个函数方法\n\n\u003e 注意`module.exports`暴露出去的一定不要是箭头函数，因为异步loader的使用是需要用到`this`的，而箭头函数不存在`this`\n\n\n### 2、在webpack中实现简单的loader\n\n```javascript\nmodule.exports = function (content, map, meta) {\n  // 其中content就是通过loader的test规则匹配到的文件资源内容\n  // map 和 meta 暂时不用了解\n  console.log('loader', content)\n  return content\n}\n```\n\n### 3、在webpack中如何引入你的loader\n\n```javascript\n// webpack.config.js\nconst path = require('path');\n\nmodule.exports = {\n  module:{\n    rules:[\n      {\n        test:/\\.js$/,\n        loader: path.resolve(__dirname,'loaders/index.js')\n      }\n    ]\n  }\n}\n\n```\n可以通过配置`resolveLoader`来让你的loader引入更加优雅\n```javascript\nmodule.exports = {\n  module:{\n    rules:[\n      {\n        test:/\\.js$/,\n        loader: 'index'\n      }\n    ]\n  },\n  resolveLoader: {\n    modules: [resolve(__dirname, 'loaders')]\n  },\n}\n```\n\n### 4、loader加载顺序\n\n我们都知道，当想要多个loader作用时，需要想`loader`属性用`use`来代替，通过`use:['loader1','loader2']`的方式来实现。\n\n基本的loader执行顺序也是从后向前执行的。\n\n但是loader并不是整体都是从后向前的，loader中注册的pitch是从前向后执行的。我们来看一下\n```javascript\n// loader中pitch的注册写法\nmodule.exports.pitch = function () {\n  console.log(\"index1-pitch\")\n}\n```\n我们可以通过注册多个loader的pitch来看下打印\n\n![loader打印顺序](https://note.youdao.com/yws/public/resource/a8003179d02ce39b6b77f5c5d8c4756b/xmlnote/WEBRESOURCEa51cc901efd7fa552402ec81515d743a/587)\n\n\n### 3、同步loader和异步loader\n\n#### 同步loader\n```javascript\n// 写法一\nmodule.exports = function (content, map, meta) {\n  console.log('loader-index3', content, map, meta)\n  // console.log('options', getOptions(this))\n  return content\n}\n\n// 写法二\nmodule.exports = function (content, map, meta) {\n  this.callback(null, content, map, meta)\n}\n```\n\n#### 异步loader\n```javascript\nmodule.exports = function (content, map, meta) {\n  const callback = this.async();\n  setTimeout(() =\u003e {\n    // 不能直接将同步的this.callback放到settimeout里面，否则会报错\n    callback(null, content, map, meta)\n  }, 2000);\n}\n```\n\u003e 注意，不可将this.callback直接放到异步操作中，否则会报错\n\n### 3、接收loader传入的options\n\nloader可能需要传入一些自定义的配置，那怎样在loader内部接收到这写参数？\n\n可以通过`loader-utils`这个库来接收，注意库的版本和使用方法\n\n```javascript\n//webpack.config.js\nmodule.exports = {\n  ///...\n  module:{\n    rules:[\n      {\n        test:/\\.js$/,\n        loader:'index',\n        options:{\n          name: 'zzz',\n          age: 21\n        }\n      }\n    ]\n  }\n}\n\n// loader\n// loader-utils v2.0.0\nconst {getOptions} = require('loader-utils');\n\nmodule.exports = function(content,map,meta){\n  // 只需要调用暴露出来的getOptions，传入this即可\n  const options = getOptions(this) || {};\n  console.log('loader-options',options)\n  this.callback(content,map,meta)\n}\n```\n![打印loader传入的options](https://note.youdao.com/yws/public/resource/a8003179d02ce39b6b77f5c5d8c4756b/xmlnote/WEBRESOURCEebf7d3273ed53daf7a0917a9eefdcfe7/590)\n\n可以看到用法很简单，只需要用暴露出的`getOptions`传入`this`就会返回在`webpack.config.js`中定义的`options`字段\n\n\n### 4、对loader传入的options进行校验\n\n借助`schema-utils`的库，同样需要注意库的版本和用法\n定义一个`schema.json`的文件来做一些字段的约束\n\n```json\n{\n  // 整体options传入的类型一般都是object\n  \"type\": \"object\",\n  // 对传入的属性进行约束\n  \"properties\": {\n    // key值为options传入的key，value是一个对象，对传入的value进行约束\n    \"name\": {\n      // 表述传入的options的类型\n      \"type\": \"string\",\n      // 如果未按照要求传的话，会抛出description中定义的信息\n      \"description\": \"输入的name必须是string类型\"\n    },\n    // 同上\n    \"age\": {\n      \"type\": \"number\",\n      \"description\": \"输入的age必须是number类型\"\n    }\n  },\n  // 是否允许options中存在以上属性之外的属性，为true允许，false为不允许\n  \"additionalProperties\": true\n}\n```\n\n然后在loader中通过`schema-utils`暴露的方法来约束下用户输入的`options`\n```javascript\n  // loader\n  const loaderUtils = require('loader-utils');\n  // schema-utils v2.7.1\n  const validate = require('schema-utils');\n\n  const schema = require('./schema.json')\n\n  module.exports = function (content, map, meta) {\n    console.log('loader-index3', content)\n    console.log('laoder-options', loaderUtils.getOptions(this))\n    const options = loaderUtils.getOptions(this) || {}\n    // 校验传入参数是否符合你的规范\n    validate(schema, options)\n\n    this.callback(null, content, map, meta)\n    // return content\n  }\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzall%2Fwebpack-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzzall%2Fwebpack-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzzall%2Fwebpack-loader/lists"}