Using relay in react native app - javascript

How to expose a graphql endpoint to react native app? Has anyone used relay in react native application? The examples in technical overview of relay https://facebook.github.io/relay/docs/getting-started.html use webpack to serve relay app and expose it to a graphql server:
import express from 'express';
import graphQLHTTP from 'express-graphql';
import path from 'path';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
import {StarWarsSchema} from './data/starWarsSchema';
const APP_PORT = 3000;
const GRAPHQL_PORT = 8080;
// Expose a GraphQL endpoint
var graphQLServer = express();
graphQLServer.use('/', graphQLHTTP({schema: StarWarsSchema, pretty: true}));
graphQLServer.listen(GRAPHQL_PORT, () => console.log(
`GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}`
));
// Serve the Relay app
var compiler = webpack({
entry: path.resolve(__dirname, 'js', 'app.js'),
eslint: {
configFile: '.eslintrc'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: {
stage: 0,
plugins: ['./build/babelRelayPlugin']
}
},
{
test: /\.js$/,
loader: 'eslint'
}
]
},
output: {filename: 'app.js', path: '/'}
});
var app = new WebpackDevServer(compiler, {
contentBase: '/public/',
proxy: {'/graphql': `http://localhost:${GRAPHQL_PORT}`},
publicPath: '/js/',
stats: {colors: true}
});
// Serve static resources
app.use('/', express.static('public'));
app.use('/node_modules', express.static('node_modules'));
app.listen(APP_PORT, () => {
console.log(`Relay Star Wars is now running on http://localhost:${APP_PORT}`);
});
but react native uses react-native packager to bundle its modules; has anyone tried using relay in the react native app?

It is now possible to use react native and relay together.
Github announcement: https://github.com/facebook/relay/issues/26
Instructions for existing RN apps: http://pulse.mixrt.com/discussion/26/technical-making-relay-work-with-existing-react-native-apps-a-step-by-step-tutorial .
Copy of the instructions:
Back up your project.
Make sure you have your GraphQL server ready and your schema.json at hand too. For more details about the latter two visit the React-Relay project page.
Ensure that you’re using `npm` version 3 or greater.
If React Native's packager (`react-native start`) is running somewhere in the background, you should stop it now.
Run: watchman watch-del-all and also: rm -rf $TMPDIR/react-* to avoid running into a known packager issue ( https://github.com/facebook/react-native/issues/4968 ).
Delete the `./node_modules` directory from your project.
Edit your `package.json` file, make sure it has the following:
"dependencies": {
"react": "^0.14.7",
"react-native": "facebook/react-native",
"react-relay": "^0.7.3"
},
"devDependencies": {
"babel-core": "^6.6.4",
"babel-preset-react-native": "^1.4.0",
"babel-relay-plugin": "^0.7.3"
}
Babel version is especially important. Make sure that your project uses babel 6.5 or later, we need it for the passPerPreset feature in .babelrc file.
Create a new file `.babelrc` and place it in your project's directory:
{
"presets": [
"./scripts/babelRelayPlugin",
"react-native"
],
"passPerPreset": true
}
Create a new file in your project's directory called `babelRelayPlugin.js` with the following content:
const getBabelRelayPlugin = require('babel-relay-plugin');
const schema = require('./schema.json');
module.exports = { plugins: [getBabelRelayPlugin(schema.data)] };
Copy your `schema.json` file to the project's directory too.
Run: npm install

You can find a working version in here, until this will be solved.

you need to install react-relay package for react-native app
Before the entry point of your react-native app, inject network layer with the url you exposed
Relay.injectNetworkLayer(
new Relay.DefaultNetworkLayer('http://localhost:8000/graphql')
);

Related

bundle an npm package AND convert it into an es module

I want to import chessground into a project of mine. It seems it's a CommonJS module, so i used browserify to import it into my web page.
browserify -r chessground > chessground.js
In order to use it in my webpage, I use
const Chessground = require('chessground').Chessground
but I saw in this project that they import it like
import {Chessground} from 'chessground'
I know they are douing with webpack, but for the life of me I can't figure out how to bundle an entire npm package into one file AND convert it into an ES module. Can anyone help me?
There is noway to bundle your packages without using a bundler like webpack or rollup.js.
If it is necessarily to use task runner you may find a way to make the bundler work with your task runner.
I had the same problem with gulpjs and wepack, and it was really painful to make it work. The solution was using a webpack and webpack plugins in gulpjs.
const webpack = require('webpack');
const webpackStream = require('webpack-stream');
const path = require('path');
const webapckJsConfig = {
mode: (process.env.APP_ENV === 'dev' && process.env.APP_DEBUG === 'true') ? 'development' : 'production',
devtool: (process.env.APP_ENV === 'dev' && process.env.APP_DEBUG === 'true') ? 'source-map' : false,
entry: {
// Website JS Files
'website/home.js': './resources/js/website/home.js',
'website/notfound.js': './resources/js/website/notfound.js',
'website/error.js': './resources/js/website/error.js',
// Admin JS Files
'admin/home.js': './resources/js/admin/home.js',
'admin/notfound.js': './resources/js/admin/notfound.js',
},
output: {
path: path.resolve(__dirname, 'public/'),
filename: '[name]',
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
},
},
],
},
};
// JavaScript lint Cehck βœ… Convert πŸ”‚ Compresse πŸ”„ Output β†ͺ πŸ“ public/js
async function scripts() {
return gulp
.src(`${JAVASCRIPT_DIR}/**/*.js`)
.pipe(webpackStream(webapckJsConfig), webpack)
.pipe(gulp.dest(`${JS_PUBLIC_DIR}`));
}
exports.scripts = scripts;
you can also check it here
You can of course take the webpack configuration and put them in external file, but you have to consider that you will confuse other developers because they will think webpack is independent and start to use it as an independent tool, so that's why I keep it in gulp.js.

How to make Webpack build on Express server started

I'm new to React and Webpack. I have webpack.config.js like this:
const webpack = require('webpack');
const path = require('path');
module.exports = {
cache: true,
entry: {
'user': ['./client/User/index']
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/static'
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
include: path.join(__dirname, 'client'),
query: { cacheDirectory: true }
}
]
},
node: { fs: 'empty' }
};
And this is my app.js entry of Express server:
import express from 'express';
import bodyParser from 'body-parser';
import morgan from 'morgan';
import webpack from 'webpack';
import session from 'express-session';
const app = express();
import config from './webpack.config';
const compiler = webpack(config);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/assets', express.static(`${__dirname}/static`));
app.use('/', require('./server/route/index'));
app.listen(3000, () => console.log('Our Blog is listening on port 3000...'));
Webpack does not build and yields any bundle in the dist folder as configured. It can only build when I use webpack-cli command. Besides, in my html document, I include the bundle as <script src='/static/user.bundle.js'></script>. I thought this must be the correct path, because it will map /static to dist folder on local machine as configured where the bundle is exactly located after build. But it keeps sending me 404 error due to resource not found. May you help me solve this?
webpack creates the file in memory. so you can't see it as per documentation.
webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path. If your page expects to find the bundle files on a different path, you can change this with the publicPath option in the dev server's configuration.
I suspect because you did not specify it as production mode that's why it's not writing to dist folder. Also you need to use webpack-dev-middleware. Here's an example for you how to use it
I hope this helps.

Can we write typescript inside a svelte component?

Is it possible to write Typescript inside the script tag in a svelte component?
I came across https://github.com/pyoner/svelte-typescript/tree/master/packages/preprocess
Which if I understand correctly is a typescript preprocessor for svelte which would allow to write typescript in svelte components. However I am not able to get it working
This is how my rollup config looks like
import svelte from "rollup-plugin-svelte";
import resolve from "rollup-plugin-node-resolve";
import replace from "rollup-plugin-replace";
import commonjs from "rollup-plugin-commonjs";
import serve from "rollup-plugin-serve";
import livereload from "rollup-plugin-livereload";
import copy from "rollup-plugin-copy";
import typescript from "rollup-plugin-typescript2";
import { terser } from "rollup-plugin-terser";
import {
preprocess,
createEnv,
readConfigFile
} from "#pyoner/svelte-ts-preprocess";
const tsEnv = createEnv();
const compilerOptions = readConfigFile(tsEnv);
const opts = {
env: tsEnv,
compilerOptions: {
...compilerOptions,
allowNonTsExtensions: true
}
};
const env = process.env.NODE_ENV;
const production = env ? env === "production" : false;
const distFolder = "dist";
export default {
input: "src/index.ts",
output: {
sourcemap: !production,
format: "iife",
name: "app",
file: `${distFolder}/bundle.js`
},
plugins: [
replace({
"process.browser": true,
"process.env.NODE_ENV": JSON.stringify(env)
}),
svelte({
// enable run-time checks when not in production
dev: !production,
// we'll extract any component CSS out into
// a separate file β€” better for performance
css: css => {
css.write(`${distFolder}/bundle.css`);
},
preprocess: preprocess(opts)
}),
// If you have external dependencies installed from
// npm, you'll most likely need these plugins. In
// some cases you'll need additional configuration β€”
// consult the documentation for details:
// https://github.com/rollup/rollup-plugin-commonjs
resolve({
browser: true,
dedupe: importee =>
importee === "svelte" || importee.startsWith("svelte/")
}),
commonjs(),
typescript({
tsconfig: "tsconfig.json",
objectHashIgnoreUnknownHack: true,
clean: production
}),
// Start dev server if not in production mode
!production &&
serve({
open: true,
contentBase: distFolder,
historyApiFallback: true,
host: "localhost",
port: 7000
}),
// Watch the `dist` directory and refresh the
// browser on changes when not in production
!production && livereload(distFolder),
// If we're building for production (npm run build
// instead of npm run dev), minify
production && terser(),
copy({
targets: [{ src: "public/**/*", dest: `${distFolder}` }]
})
],
watch: {
clearScreen: false
}
};
I am not sure If I have configured this incorrectly or if it is not possible at all to write typescript in svelte?
Yes. Svelte has official support for typescript!
https://svelte.dev/blog/svelte-and-typescript
The starter template comes with a setupTypeScript.js utility: https://github.com/sveltejs/template#using-typescript
Yes you can
This is an example of svelte + typescript + rollup
And this is an exampl of svelte + typescript + parcel
Svelte has official documentation about Typescript support.
Basically, you can add lang="ts" to your script block and svelte preprocessor will take care of compiling
<script lang="ts">
export const hello: string = 'world';
</script>
You can start a new Svelte TypeScript project using the normal template and by running node scripts/setupTypeScript.js before you do anything else:
npx degit sveltejs/template svelte-typescript-app
cd svelte-typescript-app
node scripts/setupTypeScript.js
To add Typescript to existing projects,
npm install --save-dev #tsconfig/svelte typescript svelte-preprocess svelte-check
Add tsconfig.json at the root of your project
{
"extends": "#tsconfig/svelte/tsconfig.json",
"include": ["src/**/*", "src/node_modules"],
"exclude": ["node_modules/*", "__sapper__/*", "public/*"],
}
If you're using Rollup, add the lines with + to rollup.config.js
+ import autoPreprocess from 'svelte-preprocess';
+ import typescript from '#rollup/plugin-typescript';
export default {
...,
plugins: [
svelte({
+ preprocess: autoPreprocess()
}),
+ typescript({ sourceMap: !production })
]
}
Yes, you can. Here's a how-to: Use TypeScript with Svelte / Sapper
You can try to use the next template by npx degit
https://github.com/Zimtir/ST-template
Look at README.md file
It is possible to write ts in the svelte component's script.
There are official templates available with snowpack, vite, and other build tools.
You could also build it on your own with svelte-preprocess and typescript plugin/loader for the respective build tool.
vite svelte-typescript template
snowpack svelte-typescript
template

Unable to bundle a Web Worker to be imported like an NPM package

My goal is to be able to publish a Web Worker NPM package which can be imported normally (import MyPkg from 'my-pkg') without requiring the user to import it with worker-loader (inline or otherwise)
To accomplish this, I've tried using a Babel build script as well as Webpack with worker-loader.
In the following examples there are two projects: the Web Worker package ("Package") which is npm linked to a test application ("App").
The Package is split into two files: entry.webpack.js and index.worker.js. The entry, when built and moved to /dist is designated as the main file in the package.json, and it currently looks like this:
entry.webpack.js
var MyPkg = require('worker-loader!./index.worker.js')
module.exports = MyPkg
index.worker.js
// This is just example code. It doesn't really matter
// what this code does so long as it ends up being run
// as a Web Worker.
var selfRef = self;
function ExampleWorker () {
console.log('Running Worker...');
setTimeout(function () {
// wait 10 seconds then post a message
selfRef.postMessage({foo: "bar"});
}, 10000)
}
module.exports = ExampleWorker
I then bundle the Package with Webpack:
package.json
"build": "rm -rf dist/*.* && webpack --progress"
webpack.config.js
module.exports = {
mode: 'production',
devtool: 'source-map',
entry: __dirname + '/src/entry.webpack.js',
output: {
filename: 'bundle.js',
path: __dirname + '/dist'
},
optimization: {
minimize: false
}
}
This generates two files: bundle.js and a Web Worker file as a hash: [hash].worker.js with the code we want evaluated in it. They key part in this, though, is that because we used worker-loader inline to import, the webpack compiled output looks something like:
module.exports = function() {
return new Worker(__webpack_require__.p + "53dc9610ebc22e0dddef.worker.js");
};
Finally, the App should be able to import it and use it like this:
App.js
import MyPkg from 'my-pkg'
// logging MyPkg here produces `{}`
const worker = new MyPkg()
// That throws an Error:
// Uncaught TypeError: _my_pkg__WEBPACK_IMPORTED_MODULE_4___default.a is not a constructor
worker.onmessage = event => {
// this is where we'd receive our message from the web worker
}
However, you can get it to work if, in the App itself you import the worker build like this:
import MyPkg from 'my-pkg/dist/53dc9610ebc22e0dddef.worker.js'
But, it's a requirement of the package to:
A) NOT require applications using the package to have to explicitly install worker-loader and
B) not have to reference the my-pkg/dist/[hash].worker.js explicitly.
I've tried also designating the built [hash].worker.js' as themain` in package.json but that doesn't work either.
Edit 1: I forgot to mention that I'm basing all of this off of how react-pdf does it. If you take a look in /src/entry.webpack.js and follow how it works throughout the package you'll see a few similarities.
you could try worker-loader with option:
{
test: /\.worker\.js$/,
use: {
loader: 'worker-loader',
options: {
name: '[name].[hash:8].js',
// notice here
inline: true,
fallback: false
}
}
},

Configure Webpack 4 with aliases, Babel 7 to build React components library

I'm trying to create two React projects:
React components library (only components without working application)
SPA application which uses created components (examples application)
I would like to achieve a folders structure like:
./src - directory with React components
./example - contains SPA app which uses ./src components
There are configuration files in example directory (simplest React + webpack config without HMR and other stuff):
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const aliases = require('./aliases.js');
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
}
]
},
resolve: {
alias: aliases
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
aliases.js
var path = require('path');
module.exports = {
'webpack-alias-react': path.resolve(__dirname, '../src')
};
babel.rc
{
"presets": ["#babel/preset-env", "#babel/preset-react"]
}
VSCode alias config is in jsconfig.json file.
And there is my problem.
When ./src/SimpleComponent contains code like that:
const SimpleComponent = () => {
return 'string';
};
Running npm run build command builds working application.
But when ./src/SimpleComponent returns:
const SimpleComponent = () => {
return <div>abc</div>;
};
npm run buid command throws exception:
ERROR in ../src/SimpleComponent.js Module build failed (from
./node_modules/babel-loader/lib/index.js): SyntaxError:
D:\Tranzystor\webpack-alias-react\src\SimpleComponent.js: Unexpected
token (4:9)
How to solve this webpack/Babel configuration issue?
Why is it possible to write <div> in App.js?
Is that right approach?
Whole code is here available.
I've solved that issues with Babel 7 and extended solution for that kind of issues is there:
github
It's ready to use webpack 4 + React + Babel 7 + eslint configuration.
It can be helpful for monorepo solutions.
Publishing your own components library to npm can be another application. As I mentioned above ./src directory contains small react components (content which you want to publish on npm). In ./demo directory there is spa application which shows how to use supplied components (it can be storybook for example).

Categories

Resources