相关文章
自定义loader
一、什么是自定义Loader
自定义Loader是Webpack的一个重要特性,它允许你对各种类型的资源文件进行处理,比如将Sass文件转换为CSS、将ES6代码转换为ES5等。下面是自定义Loader的基本步骤:
二、如何自定义Loader
1、创建一个Node.js模块
首先,你需要创建一个Node.js模块来定义你的Loader。这个模块需要导出一个函数,这个函数就是你的Loader的实际处理逻辑。
1 2 3 4 5 6
| module.exports = function(source) { return modifiedSource; };
|
2、处理资源文件
在导出的函数中,你可以通过source参数获取到传入的资源文件的内容,然后进行你想要的处理。处理完成后,将处理后的内容返回即可。
3、注册Loader
在Webpack配置文件中,通过module.rules配置项来注册你的Loader。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| module.exports = { module: { rules: [ { test: /\.custom$/, use: [ 'my-custom-loader' ] } ] } };
|
4、使用Loader
在你的项目中,通过import或require等方式引入需要使用该Loader的文件。当Webpack构建过程中遇到匹配该Loader的文件时,就会自动调用你定义的Loader来处理。
三、用法准则
编写 loader 时应该遵循以下准则。它们按重要程度排序。
保持 简单 。
loaders 应该只做单一任务。这不仅使每个 loader 易维护,也可以在更多场景链式调用。
使用 链式 传递。
利用 loader 可以链式调用的优势。写五个简单的 loader 实现五项任务,而不是一个 loader 实现五项任务。功能隔离不仅使 loader 更简单,可能还可以将它们用于你原先没有想到的功能。
模块化 的输出。
保证输出模块化。loader 生成的模块与普通模块遵循相同的设计原则。
确保 无状态 。
确保 loader 在不同模块转换之间不保存状态。每次运行都应该独立于其他编译模块以及相同模块之前的编译结果。
使用 loader utilities 。
充分利用 loader-utils 包。它提供了许多有用的工具,但最常用的一种工具是获取传递给 loader 的选项。schema-utils 包配合 loader-utils,用于保证 loader 选项,进行与 JSON Schema 结构一致的校验。
记录 loader 的依赖 。
如果一个 loader 使用外部资源(例如,从文件系统读取),必须声明它。
解析 模块依赖关系 。
根据模块类型,可能会有不同的模式指定依赖关系。例如在 CSS 中,使用 @import 和 url(…) 语句来声明依赖。这些依赖关系应该由模块系统解析。
提取 通用代码 。
避免在 loader 处理的每个模块中生成通用代码。相反,你应该在 loader 中创建一个运行时文件,并生成 require 语句以引用该共享模块:
避免 绝对路径 。
不要在模块代码中插入绝对路径,因为当项目根路径变化时,文件绝对路径也会变化。loader-utils 中的 stringifyRequest 方法,可以将绝对路径转化为相对路径。
使用 peer dependencies。
如果你的 loader 简单包裹另外一个包,你应该把这个包作为一个 peerDependency 引入。这种方式允许应用程序开发者在必要情况下,在 package.json 中指定所需的确定版本。
四、常用Loader
babel-loader
用于将ES6+的JavaScript代码转换为ES5,以便让现代JavaScript代码在老版本浏览器中运行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } };
|
style-loader 和 css-loader
用于处理CSS文件,可以解析CSS文件并将其注入到HTML页面中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } };
|
sass-loader 和 less-loader
用于处理Sass和Less等预处理器的文件,将其编译为普通的CSS文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.scss$/, use: [ 'style-loader', 'css-loader', 'sass-loader' ] }, { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'less-loader' ] } ] } };
|
file-loader 和 url-loader
用于处理图片、字体等文件,可以将这些文件复制到输出目录并返回文件路径。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(png|jpg|gif)$/i, use: [ { loader: 'url-loader', options: { limit: 8192, name: '[name].[ext]', outputPath: 'images/' } } ] }, { test: /\.(woff|woff2|eot|ttf|otf)$/i, use: [ { loader: 'file-loader', options: { name: '[name].[ext]', outputPath: 'fonts/' } } ] } ] } };
|
eslint-loader
用于集成ESLint,可以在构建过程中检查JavaScript代码是否符合规范。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: ['eslint-loader'] } ] } };
|
ts-loader
用于处理TypeScript文件,可以将TypeScript代码转换为JavaScript代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const path = require('path');
module.exports = { entry: './src/index.ts', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, resolve: { extensions: ['.ts', '.js'] }, module: { rules: [ { test: /\.ts$/, exclude: /node_modules/, use: ['ts-loader'] } ] } };
|
vue-loader
用于处理Vue单文件组件,可以将.vue文件中的模板、脚本和样式等内容分离开来并进行相应处理。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| const path = require('path'); const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = { entry: './src/main.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, resolve: { extensions: ['.vue', '.js'] }, module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader' } ] }, plugins: [ new VueLoaderPlugin() ] };
|
postcss-loader
用于处理CSS文件,可以使用PostCSS插件来处理CSS代码,比如自动添加浏览器前缀等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader', 'postcss-loader' ] } ] } };
|
image-webpack-loader
用于处理图片文件,可以压缩图片文件以减小文件大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(png|jpe?g|gif|svg)$/i, // 匹配图片文件 use: [ { loader: 'url-loader', // 使用url-loader处理图片文件 options: { limit: 8192, // 小于8KB的图片文件会被转换为base64编码 name: '[name].[hash:8].[ext]', // 输出文件名格式 outputPath: 'images/' // 输出到指定目录下 } }, { loader: 'image-webpack-loader', // 使用image-webpack-loader处理图片文件 options: { mozjpeg: { progressive: true, quality: 65 }, // optipng.enabled: false will disable optipng optipng: { enabled: false, }, pngquant: { quality: [0.65, 0.90], speed: 4 }, gifsicle: { interlaced: false, }, // the webp option will enable WEBP webp: { quality: 75 } } } ] } ] } };
|
json-loader
用于导入 JSON 文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const path = require('path');
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.json$/, // 匹配以.json结尾的文件 loader: 'json-loader' // 使用json-loader处理匹配到的文件 } ] } };
|