I'm trying to take a string containing markdown in a Svelte template and use that as part of a Svelte component using mdsvex I have the following code in App.svelte:
<script>
import { compile } from 'mdsvex';
import Counter from './lib/Counter.svelte'
const transformed_code = compile(`
# Hello world
This is a paragraph
<Counter />
`, {});
</script>
<div id="content"></div>
Once that's done, I want to add the result inside the #content box. When I run the compile step, I get the following error:
Uncaught (in promise) ReferenceError: process is not defined
What exactly am I doing wrong? And is this actually possible to do using mdsvex? Thanks for any help?
The module is intended to be used on the server and uses the Node variable process. The playground page shims the variable based on this: https://github.com/defunctzombie/node-process/blob/master/browser.js
You can define a process object like that and assign it on the window. Make sure that this code runs on the client:
window.process = { /* fake process here */ }
Once this is done, the code will execute, but the Counter will not work like this; the import does nothing. The output of mdsvex has to be compiled with Svelte, which generates code that tries to access an undefined Counter component.
There are multiple possible approaches:
Somehow inject the imported component constructor, e.g. via a prop (though I have run into errors because of an unset target option)
Precompile any component you want to use like this and make them available as a route that can imported from the compiled output
Compile the component on the fly. You will need to have some way to get the component source code for processing
If you have nested component imports, option 2 is probably the most viable, since you then can adjust all import URLs at the time you generate the compiled output.
Related
What I'm trying to achieve is:
Building simple react app - the template is create react app
Copying output file (main.*.js)
Pasting it in another react app
Importing render function to render the first app into the second one
Simple react app code:
interface Props {
greeting: string;
}
export module AppModule {
export const sendGreetings = ({ greeting }: Props) => {
return `Hello ${greeting}`;
};
}
Builder file code:
!function(){"use strict";var n;(n||(n={})).sendGreetings=function(n){var e=n.greeting;return"Hello ".concat(e)}}();
Trying to import this file into another app I get this error:
File 'c:/vscode/test-react-app/test-sc-react/src/main.783e0281.js' is not a module.ts(2306)
Which is obvious. I changed the output file manually to:
export function initApp(){"use strict";var n;(n||(n={})).sendGreetings=function(n){var e=n.greeting;return"Hello ".concat(e)}};
It works but the only function that I'm able to access is initApp but not sendGreetings
I've been struggling with this for a while now and I would really appreciate any helpful suggestions
I used Bit.dev for my components that are used across multiple applications & there is an article regarding your issue
https://blog.bitsrc.io/sharing-react-components-across-multiple-applications-a407b5a15186
I think it would help.
🎯 Solution #1
You can use an iframe to inject your react app:
<iframe src='path-to-your-app.html'/>
🎯 Solution #2
Go with micro-frontend architecture approach. Where a front-end app is decomposed into individual, semi-independent "microapps" working loosely together.
As a starting point, you can try npx create-mf-app instead of the CRA.
You can include your js code directly on run time. You can use window.addEventListener to load js/css incoming from an outside source. You just have to append that js to your document on the load event.
I want to create a build of my javascript application using react which currently is just a single file defined as below. It does nothing but creates a div and keeps on changing the color of the hello-world text after it mounts.
import * as React from "react";
import * as ReactDOM from "react-dom";
class App extends React.Component {
componentDidMount() {
const colorBox = ["red","blue","green"];
const element = document.getElementById("my-div");
setInterval(() => {
element.style.color = colorBox[parseInt(Math.floor(Math.random() * colorBox.length))];
}, 3000);
}
render() {
return (
<div id={"my-div"}>
Hello, World.
</div>
);
}
}
ReactDOM.render(<App />,
document.body.appendChild(document.createElement("div")));
I am using parcel js as a bundler. I bundle my javascript as parcel build index.js and this creates a build of my javascript file inside dist folder. So far, so good. But the moment, I load this javascript using a script tag on my website as:
<script type="text/javascript" src="https://mycdn.com/bundle.index.js"></script>
It throws an error
index.js:16 Uncaught TypeError: Cannot read property 'appendChild' of null
at Object.parcelRequire.Focm.react (index.js:16)
at f (index.js:1)
at parcelRequire.YOwE (index.js:1)
at index.js:1
Why it cannot access appendChild of document.body? I also checked that document.body is null. What is happening here? What is it that I am missing?
First of all I'm not sure this is a great idea to have code in the bundle that directly affects the page like this.
My guess as to why this is happening is it has to do with when the bundle is loaded in the page. Is it in head? If so document.body may not be available.
It is probably best if you are going to do something like this to use the events associated with the document being ready.
This can get complicated depending on your needs, but if you have access to jQuery, you can use .ready().
If not you can use various vanilla js options.
I guess your problem is related to the bundle or you ask for an element before it is available because it is working fine here: https://jsfiddle.net/rL6dnhps
If you load it from the head, try to put at the end of the body in order to wait for the body to be ready or wrap it inside an IIFE like below:
(function() {
// the DOM will be available here
ReactDOM.render(<App />,
document.body.appendChild(document.createElement("div")));
})();
Say I have a JS file contains 2 React Component class definition and a bunch of other things:
// a file called OuterComponent.react.js
import xxx from xxx;
import yyy from yyy;
// When does these run?
let a = 0;
a = 1;
export default class OuterComponent extends React.PureComponent<> {
render() {
return (
<View>
<InnerComponent />
</View>
);
}
}
class InnerComponent extends React.PureComponent<> {
//... something
}
Questions
When will the declaration and value setting code for 'a' run? Does it run when this file is imported/required by other files?
Can I have some flag in this file and changes from time to time, and then read the value of this flag from many other files? (like a singleton manager?) If I can, how do I export it and import it?
What does creating multiple files actually mean? (except that it breaks huge chunk of code into small chunks for better readability) Does it make any other difference?
Question 1: When will the declaration and value setting code for 'a' run? Does it run when this file is imported/required by other files?
Runs the first time the file is imported. It is not executed on subsequential imports.
Question 2: Can I have some flag in this file and changes from time to time, and then read the value of this flag from many other files? (like a singleton manager?) If I can, how do I export it and import it?
You can.
Exporting:
export let a = 0;
Importing:
import { a } from './filename.js';
Question 3: What does creating multiple files actually mean? (except that it breaks huge chunk of code into small chunks for better readability) Does it make any other difference?
Breaks code into small chunks;
Allows reuse; and
Enables encapsulation of non-exported variables/functions.
--
Check a demo of modules usage: http://plnkr.co/edit/0ImgQj2KzLj9O1D63Gq9?p=preview
Notice how a.js is loaded only once, even though it is imported both by b.js and c.js. Also see how it is exported and imported, and how when it changes, the change is picked up in other modules.
okay here it is
Answer 1: Yes, it runs when you import this file.
Answer 2: You can define some varible and export it to use in some other file, but that we do for constant values that does not change over time, like your action types etc, the thing you are referring to here is not what it is for, you want to use react Context or Redux store for that.
Answer 3: Creating multiple files is a modular approach to code, React emphasis on Composition that is the whole point of composing components in one another and build an App
Yes. This code will run immediately when the file is imported. It has nothing to do with react but with how js works.
You can share a variable in js using export keyword like this:
export let a = 0
Changes to this variable won't rerender your components because it's not part of any state.
Readability is huge impact by itself. It also allows reuse of variables names.
When working in collaboration it makes the flow much easier and reduces conflicts to only the places where they really are.
I am having a weird problem with my code, I have a styled component div that wraps around another component like this:
<ContentWidget>
<BookDay />
</ContentWidget>
(Bookday returns an empty div so this should not be a problem)
My styled component ContentWidget is an empty styled component div and is declared like this:
const ContentWidget = styled.div``;
The weird thing is I have more contentwidgets filled with content that load other components inside of my webapp. All imports are fine because it works in development perfectly fine. But whenever I run npm run build I get the following error message in my console.
ERROR in ./app/containers/Dashboard/Dashboard.js 41:18 Module parse
failed: Unexpected keyword 'var' (41:18) You may need an appropriate
loader to handle this file type. | import ForegroundBlob from
"basicComponents/ForegroundBlob/ForegroundBlob"; | import
ForegroundBlobWrapper from
"basicComponents/ForegroundBlob/ForegroundBlobWrapper";
import BookDay, { var _ref = | /#PURE/ | _jsx(ContentWidget, {}, void 0, _jsx(BookDay, {})); } from "components/BookDay/BookDay";
# ./app/containers/PracticePage/PracticePage.js 40:0-55 58:5-14 #
./app/containers/PracticePage/Loadable.js #
./app/containers/App/App.js # ./app/app.js # multi
./node_modules/react-app-polyfill/ie11.js ./app/app.js
I found out that whenever I just change the tags with a standard div tag, it seems to build like it should. I have never been as confused as I have been now.
Okay so I found out myself after a little bit of debugging.
It seems that the "#babel/plugin-transform-react-constant-elements", babel plugin messes with styled components.
I was getting this error:
Module parse failed: Unexpected keyword 'var' (13:23) You may need an
appropriate loader to handle this file type.
I am unclear on exactly why, but moving styled components I was using into the file where I was using them, rather than importing them from a different file, resolved the problem. It does in fact seem to be some sort of issue with how "#babel/plugin-transform-react-constant-elements" deals with styled-components; may have to do something with circular dependencies.
I have downloaded tracking.js and added it to my /src/assets folder
In my angular-cli.json file I have added to my scripts:
"scripts": [
"../src/assets/tracking/build/tracking-min.js"
],
issue here - In my angular component, I import tracking as follows:
import tracking from 'tracking';
and in the chrome inspection window I can hover over 'tracking' and see all of the properties as shown:
I can even call the ColorImage constructor in the console window! :
However when it tries to execute the constructor in my code I get the error about tracking being undefined:
I had assumed it was because I wasn't passing in the tracking object through the constructor in the traditional DI fashion, but when doing so I got the error that the namespace couldn't be used as a type:
The only other thing I could think of was to try and add the external reference in the main index.html file, but I got an error about strict MIME checking.
To clarify: this is all happening in my angular component constructor (when the tracking methods get exercised)
Any ideas?
go to your node_modules folder and find this file : "node_modules/tracking/build/tracking.js" . open the file and add this line of code to end of the file :
module.exports = window.tracking
save file and in use this code to import it :
import * as tracking from 'tracking';
I don't think you can use DI with that external library. However, you should be able to create a new instance in the constructor:
import tracking from 'tracking';
constructor(...) {
this.colors = new tracking.ColorTracker(...);
}
myFunction() {
this.colors.doWhateverIWant();
}
If you only want a single tracking instance throughout your app, then you'll have to create your own trackingService and inject that.
another solution is to reference the tracking.js via script tag :
<html>
<head></head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tracking.js/1.1.3/tracking-
min.js"></script>
</body>
</html>
and in your component.ts write :
(window as any).tracking.ColorTracker(["magenta"]);