I want to implement a simple chat component written in react in rails 6 application. My idea is to put js link on another webpage on which my chat will be rendered. Basically, I follow gorails.com tutorial. Source code of it: link Just for test purpose, I was able to run and embed vue components widget from that tutorial on my local machine. However in my case, instead of vue.js, I use react js. I also replaced webpacker with shakapacker.
My problem is that my javascript code is not triggered on another page, chat component does not render - no console log output either. On website where I want to embed it, inside developer tab, I can see that my embedded script has been downloaded and there is no error.
Does someone has idea what could be wrong? what I have to adjust?
Below is my code:
embed.js
import React from 'react';
import { createRoot } from 'react-dom/client';
import Chat from '../components/chats/ChatsIndex';
const event = (typeof Turbolinks === 'object' && Turbolinks.supported) ? 'turbolinks:load' : 'DOMContentLoaded';
console.log("embeded code")
document.addEventListener(event, () => {
const el = document.querySelector('#my-react-component');
const root = createRoot(el);
console.log("finding element")
console.log(el)
if (el) {
console.log('found element)
root.render(<Chat />);
}
});
rails embeded controller:
class EmbedsController < ApplicationController
include ActionView::Helpers::AssetUrlHelper
include Shakapacker::Helper
protect_from_forgery except: :show
def show
respond_to do |format|
format.js { redirect_to sources_from_manifest_entrypoints(["embed"], type: :javascript).first }
end
end
end
webpack config js
const { generateWebpackConfig } = require('shakapacker')
const webpackConfig = generateWebpackConfig()
webpackConfig.devtool = false
module.exports = webpackConfig
package.json
{
"name": "app",
"private": true,
"dependencies": {
"@babel/core": "7",
"@babel/plugin-transform-runtime": "7",
"@babel/preset-env": "7",
"@babel/preset-react": "^7.18.6",
"@babel/runtime": "7",
"axios": "^1.2.2",
"babel-loader": "8",
"bootstrap": "4.4.1",
"compression-webpack-plugin": "9",
"css-loader": "^6.8.1",
"css-minimizer-webpack-plugin": "^5.0.1",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react_ujs": "^2.6.2",
"sass": "^1.64.1",
"shakapacker": "7.0",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "5",
"webpack": "5",
"webpack-assets-manifest": "5",
"webpack-cli": "4",
"webpack-dev-server": "^4.15.1",
"webpack-merge": "5"
},
"version": "0.1.0",
"babel": {
"presets": [
"./node_modules/shakapacker/package/babel/preset.js",
"@babel/preset-react"
]
},
"browserslist": [
"defaults"
],
"devDependencies": {
"mini-css-extract-plugin": "^2.7.6",
"node-sass": "^9.0.0",
"sass-loader": "^13.3.2"
}
}
shakapacker config
# Note: You must restart bin/webpacker-dev-server for changes to take effect
default: &default
source_path: app/javascript
# You can have a subdirectory of the source_path, like 'packs' (recommended).
# Alternatively, you can use '/' to use the whole source_path directory.
source_entry_path: packs
# If nested_entries is true, then we'll pick up subdirectories within the source_entry_path.
# You cannot set this option to true if you set source_entry_path to '/'
nested_entries: false
public_root_path: public
public_output_path: packs
cache_path: tmp/shakapacker
webpack_compile_output: true
# See https://github.com/shakacode/shakapacker#deployment
shakapacker_precompile: true
# Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
# manifest_path: public/packs/manifest.json
# Additional paths webpack should look up modules
# ['app/assets', 'engine/foo/app/assets']
additional_paths: ['app/assets']
# Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false
# Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
webpack_loader: 'babel'
# Set to true to enable check for matching versions of shakapacker gem and NPM package - will raise an error if there is a mismatch or wildcard versioning is used
ensure_consistent_versioning: false
# Select whether the compiler will use SHA digest ('digest' option) or most most recent modified timestamp ('mtime') to determine freshness
compiler_strategy: digest
development:
<<: *default
compile: false
compiler_strategy: mtime
# Reference: https://webpack.js.org/configuration/dev-server/
dev_server:
https: false
host: localhost
port: 3036
# Hot Module Replacement updates modules while the application is running without a full reload
hmr: false
# If HMR is on, CSS will by inlined by delivering it as part of the script payload via style-loader. Be sure
# that you add style-loader to your project dependencies.
#
# If you want to instead deliver CSS via <link> with the mini-extract-css-plugin, set inline_css to false.
# In that case, style-loader is not needed as a dependency.
#
# mini-extract-css-plugin is a required dependency in both cases.
inline_css: true
# Defaults to the inverse of hmr. Uncomment to manually set this.
# live_reload: true
client:
# Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
overlay: true
# May also be a string
# webSocketURL:
# hostname: "0.0.0.0"
# pathname: "/ws"
# port: 8080
# Should we use gzip compression?
compress: true
inline: true
overlay: true
disable_host_check: true
use_local_ip: false
quiet: false
# Note that apps that do not check the host are vulnerable to DNS rebinding attacks
allowed_hosts: "all"
pretty: true
headers:
'Access-Control-Allow-Origin': '*'
static:
watch:
ignored: '**/node_modules/**'
test:
<<: *default
compile: true
# Compile test packs to a separate directory
public_output_path: packs-test
production:
<<: *default
# Production depends on precompilation of packs prior to booting for performance.
compile: false
# Cache manifest.json for performance
cache_manifest: true
Static website on which I want to embed my component
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Web Page</title>
</head>
<body>
<header>
<h1>Welcome to My Web Page</h1>
</header>
<nav>
<!-- Add navigation links here -->
<!-- Example:
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
-->
</nav>
<main>
<section>
<h2>Section 1</h2>
<!-- Add content for section 1 here -->
</section>
<section>
<h2><div id="my-react-component"></div></h2>
<!-- Add content for section 2 here -->
</section>
<!-- Add more sections as needed -->
</main>
<footer>
<p>© 2023 Your Website</p>
</footer>
<script src="http://localhost:3066/embed.js"></script>
</body>
</html>