babel-plugin-react-native-image-to-base64图片转Base64
babel-plugin-react-native-image-to-base64通过babel用于react-native构建时把图片转换为base64放到bundle文件中。
背景
react-native默认图片放在Assets文件夹中,但是就无法动态更新,如果全部放在服务器,小的图标也会占用请求链接,为了解决这个问题,我们需要把图片转成base64放到bundle文件里面,这样既能动态更新有解决了小图片的访问问题。
babel-plugin-react-native-image-to-base64 使用
1、安装
1
| yarn add -D babel-plugin-react-native-image-to-base64
|
or
1
| npm install --save-dev babel-plugin-react-native-image-to-base64
|
2、babel.config.js 配置
插件支持配置图片的大小来选择是否转换为base64
1 2 3 4
| module.exports = { presets: ['module:metro-react-native-babel-preset'], plugins: [['react-native-image-to-base64', {limit: 2 * 1024}]], };
|
3、转换后效果
构建前文件
1 2 3 4
| <Image source={require('./button.png')} style={{ width: 859, height: 95 }} />
|
构建后文件:
1
| n.default.createElement(T.Image,{source:{uri:"data:image/png;base64,jifsfs....",width:590,height:96},style:{width:859,height:95}})
|
这样图片就可以直接打包到bundle文件中
4、转换原理
在babel中检测到图片的require引用,然后通过解析文件路径,读取到图片地址
1 2 3 4 5 6 7 8 9 10 11 12
| const { opts: { limit = LIMIT, test = FILE_TEST }, file: { opts: { filename } } } = source; if (t.isIdentifier(ast.node.callee, { name: 'require' }) && ast.node.arguments.length === 1) { if (t.isStringLiteral(ast.node.arguments[0]) && test.test(ast.node.arguments[0].value)) { const resolveFilePath = filename.substring(0, filename.lastIndexOf("/") + 1);//获取引用图片的文件路径 const filePath = nodePath.resolve(resolveFilePath, ast.node.arguments[0].value);//读取到图片地址 const data = fs.readFileSync(filePath); if (data.length < limit) { const source = buildImageSource(t, filePath); ast.replaceWith(source); } } }
|
图片转成base64
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| const buildImageSource = (t: typeof Types, imgPath: string) => { const fileMimeType = mimeType.lookup(imgPath); const data = fs.readFileSync(imgPath); const buff = Buffer.from(data).toString('base64'); const base64 = 'data:' + fileMimeType + ';base64,' + buff; const dimensions = require('image-size')(imgPath); const source = t.objectExpression([ t.objectProperty( t.identifier('uri'), t.stringLiteral(base64), ), t.objectProperty( t.identifier('width'), t.numericLiteral(dimensions.width) ), t.objectProperty( t.identifier('height'), t.numericLiteral(dimensions.height) ), ]); return source; }
|