Embed react-native-web app into existing website - react-native

I want to embed a react-native-web application into an existing website and am currently looking for options how to do so.
The application should be a quite simple questionnaire which needs to be embedded into a website created with Elementor. My idea was to use the Elementor HTML widget and insert my application somehow, but unfortunately I cannot figure out how to do this.
I've got a bit of experience developing React Native(RN) apps but I am pretty new to web development and therefore thought it would be easier for me to go with RN and the react-native-web library.
So far, I've created a RN project using npx react-native init WebApp, copied the App.js, index.js and package.json files from react-native-web CodeSandbox template, deleted the node_modules folders and ran npm install. Then I was able to start and build this example web app with the scripts from the package.json.
Now my question, how can I use the output from the build directory and embed it into an html tag?
I also tried to use webpack with the configuration from the react-native-web docs to bundle the app but I always got a new error as soon as I fixed the last one. Is it possible to bundle a RN app into a single JS file which I could then insert into the website?
Looking forward to any advice!
Marco

I solved it by using the below webpack config. The created bundle.web.js' content is put into a script tag (<script>...</script>). This can be embedded into the HTML widget.
// web/webpack.config.js
const path = require('path');
const webpack = require('webpack');
const appDirectory = path.resolve(__dirname, '');
// This is needed for webpack to compile JavaScript.
// Many OSS React Native packages are not compiled to ES5 before being
// published. If you depend on uncompiled packages they may cause webpack build
// errors. To fix this webpack can be configured to compile to the necessary
// `node_module`.
const babelLoaderConfiguration = {
test: /\.js$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(appDirectory, 'index.web.js'),
path.resolve(appDirectory, 'src'),
path.resolve(appDirectory, 'node_modules/react-native-uncompiled'),
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
// The 'metro-react-native-babel-preset' preset is recommended to match React Native's packager
presets: ['module:metro-react-native-babel-preset'],
// Re-write paths to import only the modules needed by the app
plugins: ['react-native-web'],
},
},
};
// This is needed for webpack to import static images in JavaScript files.
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png|svg)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
},
},
};
module.exports = {
entry: [
// load any web API polyfills
// path.resolve(appDirectory, 'polyfills-web.js'),
// your web-specific entry file
path.resolve(appDirectory, 'src/index.js'),
],
// configures where the build ends up
output: {
filename: 'bundle.web.js',
path: path.resolve(appDirectory, 'dist'),
},
// ...the rest of your config
module: {
rules: [babelLoaderConfiguration, imageLoaderConfiguration],
},
resolve: {
// This will only alias the exact import "react-native"
alias: {
'react-native$': 'react-native-web',
},
// If you're working on a multi-platform React Native app, web-specific
// module implementations should be written in files using the extension
// `.web.js`.
extensions: ['.web.js', '.js'],
},
};

Related

The debugger adapter not works after vsce package

I developed a debug extension which uses an external js debugger adapter. I put the js file to the bin directory looks like this.
rootDir
--bin
----adapter.js
And I used it like this in my development environment.
{
"label": "ThingIO Debugger",
"program": "./bin/adapter.js",
"runtime": "node",
"type": "thingio-debug"
}
The code works well in my development mode, but when I packaged it to a .vsix file and install to another machine, it failed immediately.
The webpack file is below
//#ts-check
'use strict';
const path = require('path');
//#ts-check
/** #typedef {import('webpack').Configuration} WebpackConfig **/
/** #type WebpackConfig */
const extensionConfig = {
target: 'node', // vscode extensions run in a Node.js-context 📖 -> https://webpack.js.org/configuration/node/
mode: 'none', // this leaves the source code as close as possible to the original (when packaging we set this to 'production')
entry: './src/extension.ts', // the entry point of this extension, 📖 -> https://webpack.js.org/configuration/entry-context/
output: {
// the bundle is stored in the 'dist' folder (check package.json), 📖 -> https://webpack.js.org/configuration/output/
path: path.resolve(__dirname, 'dist'),
filename: 'extension.js',
libraryTarget: 'commonjs2'
},
externals: {
vscode: 'commonjs vscode' // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
// modules added here also need to be added in the .vscodeignore file
},
resolve: {
// support reading TypeScript and JavaScript files, 📖 -> https://github.com/TypeStrong/ts-loader
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
},
devtool: 'nosources-source-map',
infrastructureLogging: {
level: "log", // enables logging required for problem matchers
},
};
module.exports = [ extensionConfig ];
And the vscode:prepublish command is webpack --mode production --devtool hidden-source-map
I think it looks like the debugger adapter program is not found. So I checked the ~/.vscode/extensions, and the adapter js file exists in the right path.
Now I'm very confused about what wrong is with the extension. Maybe the path is wrong or the webpack did not compile the right file in some situation?
Can anyone give some solution or suggestion about this?

Is it possible to configure Vite to build for use inside Android app (CORS error)

Scenario
I'm using Vue2 with Vue CLI as the bundling tool, now I want to migrate Vue CLI to Vite to enhance the development experience, and the migration process is somewhat successful (thanks to this guide).
Problem
Due to a specific reason, I need to keep the production build accessible statically, without any local server required (the web app should run simply by opening up the index.html file on my machine). And with this, I encounter the problem due to the fact that Vite bundles my code in ESM format that has to be served through some server to resolve CORS policy (error screenshot below). And hence the question: Is it possible to configure Vite to build in plain JS rather than ESM?
Any help is appreciated. Thank you.
Attachments
My vite.config.js as below if it helps:
import path from "path";
import { defineConfig } from "vite";
import { createVuePlugin } from "vite-plugin-vue2";
export default defineConfig({
base: "",
css: {
preprocessorOptions: {
scss: {
additionalData: `
#use "sass:math";
#import "#/scss/utils.scss";`,
},
},
},
plugins: [createVuePlugin()],
resolve: {
extensions: [".mjs", ".js", ".ts", ".jsx", ".tsx", ".json", ".vue"]
alias: {
"#": path.resolve(__dirname, "./src"),
},
},
});

How do i exclude a directory with mocking files from webpack build with vue.config.js?

I have a directory called mock at root which contains mocking data that I use to run the app in development mode. I would like to exclude them when i build for production. I notice that it is being added into bundle whenever i run vue-cli-service build and it is bloating my app bundle size.
I am using vue-cli and so I have to work with vue.config.js.
It is not clear from the docs or any answers on the wider web how I can specify which folders/files to exclude from the build.
Here is a snippet of my vue.config.js.
module.exports = {
chainWebpack: (config) => {
config.resolve.symlinks(false)
},
configureWebpack: {
plugins: [
new CompressionPlugin()
]
},
css: {
loaderOptions: {
scss: {
prependData: `#import "#/styles/main.scss";`
}
}
}
}
This is not the perfect solution, but...
If you want to exclude that directory at build time, you can try to use require instead of import. Something like this (source):
if (process.env.VUE_APP_MY_CONDITION) {
require('./conditional-file.js');
}
But be aware of this!

Import yaml file in React Native results in number 1 instead of actual content

I'm trying to import a yaml file in React Native. I can see in the Metro defaults.js file that yaml is listed as an asset extension already.
The imported value is always the number 1 though and not the actual contents of the yaml file.
import enYaml from '../i18n/locale/en.yaml';
That is because you're loading it as a resource. So it's the resource ID. What you'd need is an answer for What is the equivalent of a webpack loader when using the metro bundler in React Native?
To do this in Expo which uses babel.config.js which Metro uses you need to add the babel-plugin-content-transformer as a dev dependency and configure it as follows
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
[
'content-transformer',
{
transformers: [
{
file: /\.ya?ml$/,
format: 'yaml',
},
],
},
],
...

How to compile my npm lib with webpack andwhat config?

I am making a js that I aim to publish npm. It will be used on both web and node.
I read webpack doc and I use this following config. Bundled and minified, it produces a 20kb package, which, IMHO, is pretty big for what it does.
Should I bundle it with webpack that way ?
{
mode: 'production',
entry: {
mylib: './src/mylib_browser.ts', // same for node
"mylib.min": './src/mylib_browser.ts'
},
watch: true,
target: 'web', // node for node
devtool: 'source-map',
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]_browser.js',
libraryTarget: 'umd',
library: 'MyLib',
umdNamedDefine: true
},
plugins: [
new UglifyJsPlugin({
sourceMap: true,
include: /\.min\.js$/,
})
],
};
And I have the same config for node.
Is it the right config to do it? How could I decrease size ?
Also, when I look at other npm package, a lot are just vanilla js. Should I just let the user of my npm package, package it as a normal dependency ?
Are you sure the minification is happening? You have UglifyJs only minifying already minified files, which seems wrong?
new UglifyJsPlugin({
sourceMap: true,
include: /\.min\.js$/, //<= remove this line
})
Also, when I look at other npm package, a lot are just vanilla js. Should I just let the user of my npm package, package it as a normal dependency ?
If your library will be packaged by consumers then I would distribute with both minified and unminified sources. This allows consumers to include the minified library via one of the npm CDNs (e.g. unpkg) when hacking around (e.g. jsfiddle) and the unminified when using the library as part of a bundled application, e.g. via webpack.
If your library is only meant for the Node environment then minification is generally considered unnecessary and even a burden should the consumer encounter a bug in your library and wish to debug it.