I have a custom npm package created in directory web_with_weback
(web react project). The package is built using webpack and contains one .png
image. The package is loaded by using npm link
inside another directory which is a react native project named mobile_with_metro
. So in short, I want to have an npm package which among other things will share images from web to mobile. So to give you some context, here is how the two projects are setup.
The web project has the following structure.
Where the index.ts contains:
import TestImage from './testimage.png';export { TestImage};
webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');const nodeExternals = require('webpack-node-externals');const CopyPlugin = require("copy-webpack-plugin");module.exports = { entry: { images: {import: './src/images/index.ts', filename: 'images/index.js'} }, externals: [nodeExternals()], output: { libraryTarget: 'commonjs' }, plugins: [ new CleanWebpackPlugin(), new CopyPlugin({ patterns: [ { from: "src/images/index.d.ts", to: "images/index.d.ts" } ], }), ], module: { rules: [ { test: /\.(ts|tsx)$/, exclude: /node_modules/, use: ['babel-loader'] }, { test: /\.(png|jpe?g|gif|svg)$/i, type: 'asset/inline' } ] } }
I use webpack (v5.19.0). I use the latest feature from webapack asset/inline
which is a replacement for the previous used url-loader.
dist
folder after webpack build looks the following.
By using npm link
in the dist
folder and npm link @test/web_with_webpack
in mobile_with_metro
I make the built package available in the mobile app directory.
Now when I try to import the image and render it in an Image
component in react native I get the following error:
error: Error: Unable to resolve module `@test/web_with_webpack/images` from `App.tsx`: @test/web_with_webpack/images could not be found within the project or in these directories: node_modules/@test/web_with_webpackIf you are sure the module exists, try these steps: 1. Clear watchman watches: watchman watch-del-all 2. Delete node_modules: rm -rf node_modules and run yarn install 3. Reset Metro's cache: yarn start --reset-cache 4. Remove the cache: rm -rf /tmp/metro-* at ModuleResolver.resolveDependency (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/node-haste/DependencyGraph/ModuleResolution.js:186:15) at ResolutionRequest.resolveDependency (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/node-haste/DependencyGraph/ResolutionRequest.js:52:18) at DependencyGraph.resolveDependency (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/node-haste/DependencyGraph.js:287:16) at Object.resolve (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/lib/transformHelpers.js:267:42) at /home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/DeltaBundler/traverseDependencies.js:434:31 at Array.map (<anonymous>) at resolveDependencies (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/DeltaBundler/traverseDependencies.js:431:18) at /home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/DeltaBundler/traverseDependencies.js:275:33 at Generator.next (<anonymous>) at asyncGeneratorStep (/home/dpordan/dev/test_webpack_metro/mobile_with_metro/node_modules/metro/src/DeltaBundler/traverseDependencies.js:87:24)
Here is the react native App.tsx
which imports the image.
import React from 'react'; import { Image } from 'react-native'; import {TestImage} from '@test/web_with_webpack/images'; const App = () => { return (<><Image source={{ uri: TestImage }}/></> ); };
To me it seems that the metro bundler can't understand what webpack has generated as an image 'path'.
Is there anything that I am missing here?
EDIT:
I tried using it in another react web project (which is setup with CRA) and it works. So, there is something that metro bundler in react native does not understand in the built package.