How to configure Expo to allow global module imports? - react-native

I am looking for a way to get rid of these
import { get_records } from ../../../../store/actions/async';
To be honest I tried a lot of tricks:
Using a package.json in the src/ with {"name": "#app"} and trying to use:
import { get_records } from '#app/store/actions/async';
Using the React Native AppRegistry name:
import { get_records } from 'main/src/store/actions/async';
The same questions goes for assets.
I've seen solution with Webpack and Babel but I don't use them with React Native.
How do you manage to do that?

If you are using Expo, you must be using babel because only ES6 version of the libraries are shipped. Even projects created with react-native init come with babel by default. Check your project folder, it should have a .babelrc file.
You can then use babel-plugin-root-import:
import { get_records } from '~/store/actions/async';
.babelrc:
{
"presets": ["babel-preset-expo"],
"plugins": [
[
"babel-plugin-root-import",
{
"rootPathSuffix": "src"
}
]
]
}

Actually I was using Babel without noticing.
npm install --save-dev babel-plugin-module-resolver
npm install --save-dev eslint-import-resolver-babel-module
.babelrc
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
},
"plugins": [
["module-resolver", {
"alias": {
"~mobile": "./src",
"~assets": "./assets"
}
}]
]
}
.eslintrc
{
"settings": {
"import/resolver": {
"babel-module": {
"alias": {
"~mobile": "./src",
"~assets": "./assets"
}
}
}
}
}
Then I use it like that:
import { addToFavorite, removeFromFavorite } from '~mobile/store/actions';
await Font.loadAsync({
'cabin-reg': require('~assets/fonts/Cabin/Cabin-Regular.ttf'),
'league-spartan': require('~assets/fonts/LeagueSpartan/leaguespartan-bold.ttf')
})

Related

Why are some images not loading on capacitor ios app using vue and vite

I am working on a capacitor app and it works fine both on browser and android phones but for one page when it's routed to it gets stuck on ios.
I have tried to check and saw it's because some files are not loading
This is my vite config
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import nodeResolve from '#rollup/plugin-node-resolve'
import json from '#rollup/plugin-json'
import alias from '#rollup/plugin-alias'
import vuetify from '#vuetify/vite-plugin'
import path from 'path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
vuetify({
autoImport: true,
}),
alias(),
],
define: {
'process.env': {}
},
build: {
rollupOptions: {
transformAssetsUrls: {
img: ['src', 'data-src']
},
plugins: [
nodeResolve({
browser: true,
preferBuiltins: false
}),
json()
]
}
},
resolve: {
alias: {
'./runtimeConfig': './runtimeConfig.browser',
'#': path.resolve(__dirname, 'src'),
},
},
server: {
fs: {
// Allow serving files from one level up to the project root
strict: false
}
},
css: {
preprocessorOptions: {
// global scss import
scss: {
charset: false,
additionalData: `
#import "#/styles/variables";
#import "#/styles/mixins.scss";
`
}
}
}
})
And this is how I am loading the images located inside src/assets folder:
I am using vue 3, vite 2.7 and capacitor 3
Update:
I'm not sure what was happening but the issue was occurring when I used vue <component /> tag. I fixed it by rewriting that part
You probably fixed this but since we fixed our, i'd like to share our solution.
We're building an app for iOS and Android using Quasar.js v2, vue3 and capacitor.
We had a similar problem when we built to production for iOS and Android.
In order To fix this we had to add viteConf.base = '/' in the build object in the quasar config file (which replaces vite.config.js), doc for base shared options here
build: {
extendViteConf (viteConf, { isServer, isClient }) {
viteConf.base = '/'
}...
Dependencies in package.json
"#capacitor-community/firebase-analytics": "^1.0.1",
"#capacitor/app": "^1.0.7",
"#capacitor/clipboard": "^1.0.2",
"#capacitor/device": "^1.1.1",
"#capacitor/keyboard": "^1.2.2",
"#capacitor/push-notifications": "^1.0.9",
"#capacitor/share": "^1.0.7",
"#capgo/capacitor-updater": "^3.3.12",
"#quasar/app-vite": "^1.0.5",
"#quasar/extras": "^1.14.3",
"quasar": "2",
"vue": "3",
Hope this can help

Vue test utils for Vue3 : document is not defined

I try to bootstrap a simple app based on the following Vue3, Vite, Vitest
I also installed the vue 3 compatible version of vue test utils to test vue components.
I have an error trying to replicate the basic example in the docs :
import { mount } from "#vue/test-utils";
import { expect, test } from 'vitest'
// The component to test
const MessageComponent = {
template: "<p>{{ msg }}</p>",
props: ["msg"],
};
test("displays message", () => {
const wrapper = mount(MessageComponent, {
props: {
msg: "Hello world",
},
});
// Assert the rendered text of the component
expect(wrapper.text()).toContain("Hello world");
});
FAIL src/tests/hello-world.test.ts > displays message
ReferenceError: document is not defined
❯ Proxy.mount node_modules/#vue/test-utils/dist/vue-test-utils.cjs.js:7840:14
7838| addToDoNotStubComponents(component);
7839| registerStub({ source: originalComponent, stub: component });
7840| var el = document.createElement('div');
| ^
7841| if (options === null || options === void 0 ? void 0 : options.attachTo) {
7842| var to = void 0;
Re-running tests... [ src/tests/hello-world.test.ts ]
My package.json
{
"name": "vite-vue3-poc",
"version": "0.0.0",
"scripts": {
"serve": "vite preview",
"build": "vite build",
"coverage": "vitest --coverage",
"dev": "vite",
"preview": "vite preview",
"test": "vitest"
},
"dependencies": {
"#mdi/font": "5.9.55",
"prettier": "^2.5.1",
"roboto-fontface": "*",
"vue": "^3.2.25",
"vuetify": "^3.0.0-alpha.0",
"webfontloader": "^1.0.0"
},
"devDependencies": {
"#vitejs/plugin-vue": "^2.0.0",
"#vue/cli-plugin-babel": "5.0.0-beta.7",
"#vue/cli-service": "5.0.0-beta.7",
"#vue/test-utils": "^2.0.0-rc.18",
"#vuetify/vite-plugin": "^1.0.0-alpha.3",
"sass": "^1.38.0",
"sass-loader": "^10.0.0",
"vite": "^2.7.2",
"vitest": "^0.1.23",
"vue-cli-plugin-vuetify": "~2.4.5",
"vuetify-loader": "^2.0.0-alpha.0"
}
}
vite.config.js
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import vuetify from "#vuetify/vite-plugin";
import path from "path";
/// <reference types="vitest" />
// Configure Vitest (https://vitest.dev/config)
// https://vitejs.dev/config/
export default defineConfig({
test: {
/* for example, use global to avoid globals imports (describe, test, expect): */
// globals: true,
},
plugins: [
vue(),
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
vuetify({
autoImport: true,
}),
],
define: { "process.env": {} },
resolve: {
alias: {
"#": path.resolve(__dirname, "src"),
},
},
});
Finally fixed it by manually installing jsdom and declaring it in vite.config.ts
export default defineConfig({
test: {
globals: true,
environment: "jsdom",
},
...
}
Like others have pointed out, you need to set environment: 'jsdom' in vitest.config.ts. Alternatively, you could set environment: 'happy-dom'.
In the example provided by the Vitest documentation, they used to use happy-dom instead of jsdom. From what I gather, happy-dom is a faster alternative to jsdom. I'm using happy-dom in my project, and I'm happy with it! :)
EDIT: I changed my wording to reflect the fact that the Vitest example used to use happy-dom. As of this writing, it uses jsdom.
No need to install jsdom manually. By setting environment: "jsdom" in the test property, Vitest automatically asks you if you want to install it.
This config helped me
Your vite.config.ts
import { fileURLToPath, URL } from "node:url"
import { defineConfig } from "vite"
import type { UserConfig as VitestUserConfigInterface } from "vitest/config"
import vue from "#vitejs/plugin-vue"
const vitestConfig: VitestUserConfigInterface = {
test: {
globals: true,
environment: "jsdom",
},
}
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
test: vitestConfig.test,
})

How to add custom theme to element-ui in nuxt?

I want to add custom theme to element-ui.
I have installed element-ui, babel-plugin-component.
Nuxt src directory
module.exports = {
srcDir: 'client/',
...
Add nuxt plugin
import Vue from 'vue';
import {
Button,
...
} from 'element-ui';
import lang from 'element-ui/lib/locale/lang/ru-RU';
import locale from 'element-ui/lib/locale';
locale.use(lang);
Vue.use(Button);
...
Add plugin to nuxt config
{ src: '#/plugins/element-ui.js' },
.babelrc file
{
"babelrc": true,
"cacheDirectory": false,
"presets": ["#nuxt/babel-preset-app"],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "~client/assets/styles/element-ui/theme"
}
]
]
}
Theme don't load.
How to fix it?

Jest TransformIgnorePatterns all node_modules for React-Native Preset

I'm New to jest,
After setting-up jest config in my project's - package.json,
Package.json
"jest": {
"preset": "react-native",
"verbose": true,
"moduleDirectories": ["node_modules", "src"],
"transformIgnorePatterns": ["node_modules/(?!(react-native-cookies)/)"]
},
i already Tried this for ignoring all node modules:-
"transformIgnorePatterns": ["node_modules"]
But not working For me
and .babelrc
{
"presets": ["react-native"]
}
My LoginScreen-Test.js Code:-
TestCase
import 'react-native';
import React from 'react';
import LoginScreen from '../src/components/LoginScreen';
import renderer from 'react-test-renderer';
it('renders correctly', () => {
const hello = renderer.create(<LoginScreen/>).toJSON();
expect(hello).toMatchSnapshot();
});
i begin to run --> npm test or npm test -- -u
it reflects me with following error:-
Terminal Output
FAIL tests/LoginScreen-test.js ● Test suite failed to run
/Users/Documents/Projects/node_modules/react-native/Libraries/Utilities/Platform.ios.js:31
get isTesting(): boolean {
^
SyntaxError: Unexpected token :
at ScriptTransformer._transformAndBuildScript (node_modules/jest-runtime/build/script_transformer.js:316:17)
at Object.get Platform [as Platform] (node_modules/react-native/Libraries/react-native/react-native-implementation.js:111:27)
at Object.<anonymous> (node_modules/react-native-cookies/index.js:9:17)
I want to Ignore All Node modules by TransformIgnorePattern, but seems it is not Working for my React-Native Preset,..
Looking for the Helpful Answer...
This error shows that "react-native" has not been transformed:
react-native/Libraries/Utilities/Platform.ios.js:31
"transformIgnorePatterns": ["node_modules"] won't work because it is pretty much the default behavior.
Have you tried using the official recommendation config? It should look something like this for your project:
"transformIgnorePatterns": [
"node_modules/(?!(react-native|react-native-cookies)/)"
]
the ?! is important because it means ignore everything in the node_modules EXCEPT for react-native and react-native-cookies.
This is the correct config in 2022
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native(-.*)?|#react-native(-
community)?)/)"
]
I hame the same issue. This solution above doesnt work for me.
jest.config.js
module.exports = {
preset: '#testing-library/react-native',
setupFilesAfterEnv: ['#testing-library/jest-native/extend-expect'],
transformIgnorePatterns: [
'node_modules/(?!((jest-)?react-native(-.*)?|#react-native(-community)?)/)',
],
setupFiles: [
'./node_modules/react-native-gesture-handler/jestSetup.js',
'<rootDir>/jest.setup.js',
],
moduleNameMapper: {
'\\.svg': '<rootDir>/__mocks__/svgMock.js',
},
collectCoverage: false,
coverageDirectory: '__coverage__',
coveragePathIgnorePatterns: ['/node_modules/', '.*.svg', '.*.png'],
}

Publish a react component to npm and reuse it

I am trying to publish a basic React component to my npm registry and trying to reuse it. I think I am not following proper way to distribute my react component. Here's what I have:
This is the directory structure:
MyReactPOC
-> main.jsx
-> .npmrc
-> package.json
-> webpack.config.js
main.jsx
import React from 'react';
class MyComponent extends React.Component {
render() {
return (
<div>
<p>Hello from MyComponent!!</p>
</div>
);
}
}
export default MyComponent
package.json
{
"name": "#pankaj/my-component",
"version": "1.0.7",
"description": "POC for importing a component",
"main": "./dist/bundle.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"prepublish": "webpack --config webpack.config.js"
},
"repository": {
"type": "git",
"url": "my git repo"
},
"author": "Pankaj",
"license": "ISC",
"dependencies": {
"react": "~15.5.4",
"react-dom": "~15.5.4"
},
"devDependencies": {
"babel-cli": "~6.24.1",
"babel-core": "~6.24.1",
"babel-loader": "~6.4.1",
"babel-preset-es2015": "~6.24.1",
"babel-preset-react": "~6.24.1",
"webpack": "~2.4.1"
}
}
webpack.config.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './main.jsx',
output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js' },
module: {
loaders: [
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
},
};
I import the module in another project using import MyComponent from '#pankaj/my-component'.
When I use this component like
I get the following error:
React.createElement: type is invalid -- expected a string (for
built-in components) or a class/function (for composite components)
but got: object. You likely forgot to export your component from the
file it's defined in.
Please help me understand the right way to distribute the react components so that they can be used by other projects within my org.
Here is how I use this component:
ComponentUse.js
import React from 'react';
import ReactDOM from 'react-dom';
import MyComponent from '#pankaj/my-component';
ReactDOM.render(
<MyComponent/>,
document.getElementById('root')
);
I have an index.html that has the 'root' div.
Every react component needs a return statement. Add a return statement in your render function and it should work.
...
render() {
return (<div>...</div>)
}
You cannot directly render to the Dom from your react component, instead return it so that react can work with it.
In webpack, specify your output file as a library using output.library https://webpack.js.org/concepts/output/#output-library
I wrote a full Medium story because I had the same issue as you and there is no information about it.
Check it out: https://medium.com/#BrodaNoel/how-to-create-a-react-component-and-publish-it-in-npm-668ad7d363ce
The main fix is to add libraryTarget: 'umd' in the webpack.config.js file
If you export with es6 syntax with babel, your component will be in MyComponent.default namespace. To avoid this you should install:
npm i --save-dev babel-plugin-add-module-exports in your .babelrc?
and add it to the babel conf:
{
"presets": [ "es2015", "react"],
"plugins": ["add-module-exports"]
}