{"id":18389594,"url":"https://github.com/anseki/skeleton-loader","last_synced_at":"2025-04-07T02:34:34.778Z","repository":{"id":57362260,"uuid":"75990473","full_name":"anseki/skeleton-loader","owner":"anseki","description":"Loader module for webpack to execute your custom procedure. It works as your custom loader.","archived":false,"fork":false,"pushed_at":"2023-01-09T22:18:13.000Z","size":87,"stargazers_count":18,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-19T10:42:28.688Z","etag":null,"topics":["content","custom","custom-loader","custom-procedure","edit","function","instant","javascript","loader","modify","webpack","webpack-configuration"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anseki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-12-09T01:38:36.000Z","updated_at":"2025-01-05T20:40:09.000Z","dependencies_parsed_at":"2023-02-08T14:40:12.950Z","dependency_job_id":null,"html_url":"https://github.com/anseki/skeleton-loader","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fskeleton-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fskeleton-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fskeleton-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anseki%2Fskeleton-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anseki","download_url":"https://codeload.github.com/anseki/skeleton-loader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247583517,"owners_count":20962048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["content","custom","custom-loader","custom-procedure","edit","function","instant","javascript","loader","modify","webpack","webpack-configuration"],"created_at":"2024-11-06T01:43:53.718Z","updated_at":"2025-04-07T02:34:29.759Z","avatar_url":"https://github.com/anseki.png","language":"JavaScript","readme":"# skeleton-loader\n\n[![npm](https://img.shields.io/npm/v/skeleton-loader.svg)](https://www.npmjs.com/package/skeleton-loader) [![GitHub issues](https://img.shields.io/github/issues/anseki/skeleton-loader.svg)](https://github.com/anseki/skeleton-loader/issues) [![David](https://img.shields.io/david/anseki/skeleton-loader.svg)](package.json) [![license](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\nLoader module for [webpack](https://webpack.js.org/) to execute your custom procedure. It works as your custom loader.\n\nBy default, skeleton-loader only outputs the input content. When you specify a function, skeleton-loader executes your function with the input content, and outputs its result. The function does something, it might edit the content, it might parse the content and indicate something in a console, it might do anything else.\n\nThat is, you can specify a function in webpack configuration instead of writing new custom loader.\n\nskeleton-loader is useful when:\n\n- You couldn't find a loader you want.\n- You don't want to write a special loader for your project.\n- You want to add something to the result of another loader.\n- You want to do additional editing.\n- etc.\n\nFor example:\n\n```js\n// webpack.config.js\nmodule.exports = {\n  entry: './app.js',\n  output: {\n    filename: 'bundle.js'\n  },\n  module: {\n    rules: [{\n      test: /\\.js$/,\n      loader: 'skeleton-loader',\n      options: {\n        procedure: function(content) {\n          // Change the input content, and output it.\n          return (content + '').replace(/foo/g, 'bar');\n        }\n      }\n    }]\n  }\n};\n```\n\n```js\n// webpack.config.js\n// ...\ntest: /\\.html$/,\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(content) {\n    // Remove all elements for testing from HTML.\n    return (content + '').replace(/\u003cdiv class=\"test\"\u003e[^]*?\u003c\\/div\u003e/g, '');\n  },\n  toCode: true\n}\n```\n\n```js\n// webpack.config.js\n// ...\ntest: /\\.json$/,\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(content) {\n    var appConfig = JSON.parse(content);\n    // Check and change JSON.\n    console.log(appConfig.foo);\n    appConfig.bar = 'PUBLISH';\n    return appConfig;\n  },\n  toCode: true\n}\n```\n\n```js\n// webpack.config.js\n// ...\n// skeleton-loader options\noptions: {\n  // Asynchronous mode\n  procedure: function(content, options, callback) {\n    setTimeout(function() {\n      callback(null, 'Edited: ' + content);\n    }, 5000);\n  }\n}\n```\n\n## Installation\n\n```\nnpm install --save-dev skeleton-loader\n```\n\n## Usage\n\nDocumentation:\n\n- [Loaders](https://webpack.js.org/concepts/loaders/)\n- [Using loaders](http://webpack.github.io/docs/using-loaders.html) (for webpack v1)\n\n## Options\n\nYou can specify options via query parameters or an `options` (or `skeletonLoader` for webpack v1) object in webpack configuration.\n\n### `procedure`\n\n*Type:* function  \n*Default:* `undefined`\n\nA function to do something with the input content. The result of the `procedure` is output.  \nThe following arguments are passed to the `procedure`:\n\n- `content`  \nThe content of the resource file as string, or something that is passed from previous loader. That is, if another loader is chained in `loaders` list, the `content` that is passed from that loader might not be string.\n- `options`  \nReference to current options. This might contain either or both of `sourceMap` and `meta` if those are passed from previous loader. Also, it might contain [`options.resourceOptions`](#optionsresourceoptions).\n- `callback`  \nA callback function for asynchronous mode. If the `procedure` doesn't receive the `callback`, the loader works in synchronous mode.\n\nIn the `procedure` function, `this` refers to the loader context. It has `resourcePath`, `query`, etc. See: https://webpack.js.org/api/loaders/#the-loader-context\n\nThe result of the `procedure` can be any type such as `string`, `Object`, `null`, `undefined`, etc.  \nFor example:\n\n```js\n// app.js\nvar config = require('config.json');\n```\n\n```js\n// webpack.config.js\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(config) {\n    if (initialize) {\n      return; // make config be undefined\n    }\n    return process.env.NODE_ENV === 'production' ? config : {name: 'DUMMY'}; // data for test\n  }\n}\n```\n\nIn synchronous mode, the `procedure` has to return the content. The content is output as JavaScript code, or passed to next loader if it is chained.\n\nFor example:\n\n```js\n// webpack.config.js\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(content, options) {\n\n    // Do something with content.\n    console.log('Size: ' + content.length);\n    content = (content + '').replace(/foo/g, 'bar'); // content might be not string.\n\n    // Check the resource file by using context.\n    if (this.resourcePath === '/abc/resource.js') {\n\n      // Change current option.\n      options.toCode = true;\n    }\n\n    // Return the content to output.\n    return content;\n  }\n}\n```\n\nIf the `procedure` receives the `callback`, the loader works in asynchronous mode. To return either or both of SourceMap and meta data, it must be asynchronous mode.  \nIn asynchronous mode, the `procedure` has to call the `callback` when it finished.\n\nThe `callback` accepts the following arguments:\n\n- `error`  \nAn error object, when your procedure failed.\n- `content`  \nThe content that is output as JavaScript code, or passed to next loader if it is chained. This can be any type such as `string`, `Object`, `null`, `undefined`, etc.\n- `sourceMap`  \nAn optional value SourceMap as JavaScript object that is output, or passed to next loader if it is chained.\n- `meta`  \nAn optional value that can be anything and is output, or passed to next loader if it is chained.\n\nFor example:\n\n```js\n// webpack.config.js\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(content, options, callback) { // Switches to asynchronous mode\n    // Do something asynchronously.\n    require('fs').readFile('data.txt', function(error, data) {\n      if (error) {\n        // Failed\n        callback(error);\n      } else {\n        // Done\n        callback(null, data + content);\n      }\n    });\n  }\n}\n```\n\n#### `options.resourceOptions`\n\nThe `options` argument has `resourceOptions` property if a query string is specified with the resource file, and it is an object that is parsed query string.  \nThis is useful for specifying additional parameters when importing the resource files. For example, you can specify the behavior with resource files.\n\n```js\nvar\n  all = require('file.html'),\n  noHead = require('file.html?removeHead=yes'),;\n```\n\n```js\n// webpack.config.js\n// ...\n// skeleton-loader options\noptions: {\n  procedure: function(content, options) {\n    if (options.resourceOptions \u0026\u0026 options.resourceOptions.removeHead) {\n      content = content.replace(/\u003chead[^]*?\u003c\\/head\u003e/, ''); // Remove \u003chead\u003e\n    }\n    return content;\n  }\n}\n```\n\nThe query string is parsed in the same way as [loader-utils](https://github.com/webpack/loader-utils#options-as-query-strings).\n\n### `toCode`\n\n*Type:* boolean  \n*Default:* `false`\n\nWhen the content is not JavaScript code (e.g. HTML, CSS, JSON, etc.), a loader that is specified as a final loader has to convert the content to JavaScript code and output it to allow another code to import the content.  \nIf `true` is specified for `toCode` option, the content is converted to JavaScript code.  \nIf the loader is specified as not a final loader, this option is ignored (i.e. the content is not converted, and it is passed to next loader).\n\nFor example:\n\n```js\n// webpack.config.js\nmodule.exports = {\n  // ...\n  module: {\n    rules: [\n      // HTML code is converted to JavaScript string.\n      // It works same as raw-loader.\n      {test: /\\.html$/, loader: 'skeleton-loader?toCode=true'},\n\n      // JSON data is converted to JavaScript object.\n      // It works same as json-loader.\n      {\n        test: /\\.json$/,\n        loader: 'skeleton-loader',\n        options: {\n          procedure: function(content) { return JSON.parse(content); },\n          toCode: true\n        }\n      }\n    ]\n  }\n};\n```\n\n```js\n// app.js\nvar html = require('file.html');\nelement.innerHTML = html;\n\nvar obj = require('file.json');\nconsole.log(obj.array1[3]);\n```\n\n### `cacheable`\n\n*Type:* boolean  \n*Default:* `true`\n\nMake the result cacheable.  \nA cacheable loader must have a deterministic result, when inputs and dependencies haven't changed. This means the loader shouldn't have other dependencies than specified with [`context.addDependency`](https://webpack.js.org/api/loaders/#this-adddependency).  \nNote that the default value is `true`.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanseki%2Fskeleton-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanseki%2Fskeleton-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanseki%2Fskeleton-loader/lists"}