ES6 React server-side rendering, how to import a React Component? - node.js

I'm transpiling ES6 to ES5.
BabelJS for the NodeJS Express server files and server-side rendering output to a directory build/server/.
Browserify + babelify for the ReactComponents output to a build/client/bundle.js file
When trying to import a React Component from build/client/bundle.js to a build/server/ file the app crashes because I'm importing an untranspiled ReactComponent.
How could I import the ReactComponent without duplicating the code in the server (re-using the code from the client/bundle.js)?

You have a few solutions:
Your server code doesn't need to be pre-compiled. If you run it with babel-node, it will be compiled on-the-fly.
You could bundle your server code. I don't know any resource on how to do it with browserify, but here's a very good resource to get started with webpack for your backend.
You could build your client code alongside your server code.

Related

Express Server Restart does not load changes in React Components from JSX files

We have the following setup:
NodeJS express server that renders a document from React components defined in .tsx files. The html is used to generate PDF files on the server side.
We use ts-node-dev in order to detect changes in the typescript files (.ts and .tsx files), and to reload the server.
Now we have the problem that changes in the .tsx files are detected, and I see the following log entry:
[INFO] 17:27:03 Restarting: /Users/.../file.tsx has been modified
However, when I trigger the PDF generation again, the changes I made in the .tsx files to the react components are not reflected, I only see them after I kill ts-node-dev and start the server again manually.
Any ideas why the components are sticky? Is there a way how I can make sure they get reloaded?
Our setup:
Node v10.16.0
express: 4.17.1
react: ^16.8.6
react-dom: ^16.8.6
ts-node: ^8.3.0
typescript: 3.5.2
ts-node-dev: 1.0.0-pre.40

how to use node module with es6 import syntax in typescript

I have a typescript project which has uses one of our node modules which normally runs in our front-end. We are now looking to use this module in node on our server.
The module uses es6 import syntax import { props } from 'module/file'
When I include a ref in typescript using either of the following methods
import { props } from 'module/file';
var props = require('module/file');
I get the following error from typescript
unexpected token 'import'
(function (exports, require, module, __filename, __dirname) { import
It's a big job to re-write the module, and I've tried using babel with babel-plugin-dynamic-import-node, as well as SystemJS.
The problem with these systems is that they are all asynchronous, so I can't import the module in the standard fashion, so I would need to do a whole bunch of re-write when we get to the point that I can use import natively in node.js.
I can't be the first person to have this issue, but I can't seem to find a working solution.
--------------- update with set-up -------------
In response to #DanielKhoroshko's response. The original module I am trying to import is normally packaged by webpack in order to use on the front-end. I am now trying to use this same module both server-side and in the front-end (via webpack on the front-end) without re-writing the imports to use require and without running webpack to bundle the js to use on the server.
To be clear, the original module is written in JS, our service which is trying to use this module is written in typescript and transpiled. When the typescript tries to require the old module which uses import, it is at this point that we are running into the issue.
------------------ some progress ---------------------------
I've made some progress by creating a file in my imported module which uses babel in node.js to transpile the es6 code into commonJS modules.
I've done this via
var babel = require("babel-core")
var store = babel.transformFileSync(__dirname + '/store.js', {
plugins: ["transform-es2015-modules-commonjs"]
});
module.exports = {
store: store.code
}
I can now get the store in my new node.js project. However, the submodules within the store.js file are not included in the export.
So where in my module, it says
import activities from './reducers/activities';
I now get an error
Cannot find module './reducers/activities'
How can I get babel to do a deep traversal to include the sub-directories?
unexpected token 'import' means you are running es-modules code in environment that doesn't support import/export commands. If you are writing you code in TypeScript it's important to transpile it first before building for the browser or use ts-node to run it server-side.
If you are using webpack there are loaders ts-loader and awesome-typescript-loader
What is your setup?
To describe the module you would need to create an activities.d.ts file in the same folder where the js-version (I understood it is called activities.js and containers a reducer) resides with the following (approx.):
import { Reducer } from 'redux';
export const activities: Reducer<any>;
#Daniel Khoroshko was right in many ways, I ended up finding #std/esm which lets you import es6 modules and worked find for fetching the included imports as well.
var babel = require('babel-register')({
presets: ["env"]
});
require = require('#std/esm')(module);
var store = require('ayvri-viewer/src/store');
exports.default = {
store: store
}
I had to run babel to get a consistent build from es6 to node compatible es5

How to bundle typescript-node-express application

I want to build a complete fullstack web app.
My server side code is in typescript.
I would like to configure my project such that it will be from the following structre:
projectFolder/src/(server-side typescript files) - contians an index.ts main file
projectFolder/public/(client-side code) - served from index.ts express code.
projectFolder/serverCodeBundle.js
While I am working on my server side code I want some watch command to run in the backgorund and bundle all my ts files to some serverCodeBundle.js such that it would be sourcemapped to original ts files.
To keep things simple let's assume my server-side code looks like this(for simplicity I have ommited client code serving):
/src/index.ts:
import {A} from './A'
new A()
/src/A.ts:
export class A {
constructor() {
throw new Error("A error")
}
}
Running nodemon serverCodeBundle.js an error message should appear specifying the error come from A.ts.
I have tried tsify[together with require("source-map-support").install() in the beginning of each ts file(and in index.ts only too) and sourcemap option on in tsconfig] but couldn't get it to work.
Is there any tsify configuration, yeoman generator or any other bundler which can do that?

How do I use Webpack with ReactJS and NodeJS?

How do I use Webpack with ReactJS and NodeJS? My problem is both the server and client have source that needs to be transpiled through (babble et. al.) but the Webpack config file only has one output file.
What I need is my node app build and my client side app built and put in build/.
Webpack won't compile your server code. You'll need to configure babel to transpile your server code when the server starts. Why do you need both server and client code in a /build/ directory? It's better to keep them separate.

node.js sharing javascript file between client and server

I want a JavaScript file to be included in my client as well as server.
Having some issues. Please help me.
Code:
require('app.js');
or
<script src='app.js'></script>
Which one should I use?
You can use Browserify to bundle your node module then import that js file with:
<script src='app.js'></script>
The require() function will now be on the global namespace and you can call the following to make the module available to use:
var app = require('app.js');
Note: in Browserify you'll need to export the module you want to import using require.

Resources