Following my previous question, I have followed webpack guidelines of using multiple targets to build my NPM package. https://webpack.js.org/concepts/targets/#multiple-targets
I now have two different output files, index.js which is the browser bundle and index.node.js which is obviously supposed to run on the backend.
The app should run on both browser and Node, the code is mostly reused but there is some big difference around accessing files etc. which means I do need two separate files depending on what platform should the app run.
My question is how should I publish this library in a way that user can consume it like import {//SOME OBJECT} from 'my-published-library' when they import it from NPM regardless if they are using it on the browser or in their node application? If I try that at the moment it always defaults to index.js which works in the browser but not in Node.
Not sure if this is what you're looking for but if you are installing for the browser, the package.json provides a field to set the entry point.
https://docs.npmjs.com/files/package.json#browser
Related
Background
I have a django app that I want to create an admin widget for. The widget will display text in a particular way (like a terminal). It's so that app admins can see forwarded logs from an analytics process that is orchestrated by django (the app is django-twined).
To do that I want to use something like terminal-kit or one of the other libraries requiring npm install <whatever>
Building the app
The app is built in docker, and I don't want the entire node stack to end up in my production image.
I could use a multi-stage docker build; so install node and a lib from NPM in the first stage, then copy the library from node_modules in the second stage, but this feels unnecessarily slow.
Also, because all I'm doing then is using the raw js static assets that get bundled with the django app, I'm not sure how to go about importing the module (or if this is even possible).
The questions
Can I install an npm module without having the node stack present, and therefore avoid dealing with unwieldy multi stage builds?
How can I then import or require the contents of that module into vanilla javascript to use in a django widget?
Is this even in general possible? If it looks like moving a mountain, I'll give up and just slap a text area with monospace font on there... but it would be nice if log highlighting and colours were properly handled in a terminal-like way.
Can I install an npm module without having the node stack present, and therefore avoid dealing with unwieldy multi stage builds?
You can rollup an npm package using a dev tool like Browserify.
This can be done by rolling up the entire package using something like:
browserify --require terminal-kit
Browserify will parse the package and create a single JS file that you can try loading in the browser. There are some limitations to this so I'd recommend experimenting and exploring the Browserify docs.
How can I then import or require the contents of that module into vanilla javascript to use in a django widget?
You can do this by including a Django template file reference in the backend admin class definition. In the template you'll need to include an html JS source tag that points to the JS script you want to load. Django can include static files when building, you can use that to include the JS file during build time and then a local resource reference to point the template file to the right location.
Is this even in general possible?
Generally speaking this is definitely possible but YMMV. It boils down to the complexities of the npm package and what exactly it is trying to do in the browser.
In steps I would do the following:
Use Browserify to convert the npm package to a single JS file.
Create an html file that loads the local JS file, open this in the browser.
Open the console and see if the commands/context you're hoping to reproduce are working as expected in the browser. You could also write another vanilla JS file and load that in the html file to test.
Include the JS file reference in the Django admin template/widget.
Write custom JS code in the widget that uses/shows the globally instantiated JS script.
This strategy is based off my personal experience, I have had success following this strategy, hopefully it is helpful.
This is the most basic question.
In every online example I see, to get a website running with NodeJS and React two seperate programs/servers are created. One runs on port 3000 and the other on 3001. Is this necessary?
If react is a frontend engine why does it have to run on a port or a server?
Im confused as to why they always use create-react-app which may be running on its own server im not sure.
I would like to create app.js import 'express' to handle requests and also import React on the same file, but I run into compilation errors, will this approach work?
Is this necessary?
No, this isn't ever necessary and is only typically done in development.
If react is a frontend engine why does it have to run on a port or a server?
Webpack (the thing typically bundling your React code for browser usage, similar tools are vite/snowpack) creates a server for live updates and errors so changes in your React automatically propagate to the UI.
This is only done during development and not in production. It's a convenience feature while developing the code.
I would like to create app.js import 'express' to handle requests and also import React on the same file, but I run into compilation errors, will this approach work?
Frontend code usually has a build step where you run npm run build which runs webpack --production over your code (or esbuild or other similar tools). After this point all your frontend code is typically static files (.js .html .css etc) from which point you just serve them from static file storage (usually a CDN for faster load times in different geographies).
I'm learning nodejs and vuejs to modify an already created web site.
I installed nodejs, vue and vue-cli and I launched "npm run serve" which apparently start "vue-cli-serve serve"
The problem is that I don't understand what this web server do on files, in this documentation : https://cli.vuejs.org/guide/prototyping.html , it's told:
It automatically infers the entry file in the current directory - the entry can be one of main.js, index.js, App.vue or app.vue. You can also explicitly specify the entry file:
vue serve MyComponent.vue
Ok, but does it run main.js, does it include it into a js file which is the loaded by the index.html on the client broswer.
I see in the browser that the page load a js file named like that: app.23d...js
My question is how this js file is created?
For instance, when the content of main.js is this one:
import './css/icon.css'
Vue.use(VueResource)
Vue.use(VueScrollTo)
what is the output in the app....js file?
It seems it doesn't work at all like php which I usually use on web server
Thank you
Vue uses Webpack to convert your potentially-numerous distinct .js files into bundles with names like app.23d92ab88708...js
From the Webpack documentation:
Concepts
At its core, webpack is a static module bundler for modern JavaScript applications. When webpack processes your application, it internally builds a dependency graph from one or more entry points and then combines every module your project needs into one or more bundles, which are static assets to serve your content from.
I don't suggest trying to get into the details of how Webpack works
This will take a lot of time. If you have an existing Vue project, you are much better off spending your time interpreting that as a Vue project, and accepting that the conversion into the actual app.23d.....js file or files is an automatic process that you do not need to involve yourself in.
It will avoid a colossal waste of time
It won't advance your understanding of how the Vue project works
Whatever you learn about the exact workings of today's Webpack, may be completely wrong about tomorrow's Webpack.
Nevertheless the interface that Webpack provides to you as a Vue programmer will remain constant over future versions.
This is the concept of software abstraction. It is highly advantageous to not have to know how every step of every process works, as long as you know how it is designed to respond to actions you take at a high level.
Horrific thought
I have just re-read your opening sentence:
I'm learning nodejs and vuejs to modify an already created web site.
Please tell me that you are not trying to modify an already created web site where you only have the compiled website available, without the Vue source code? That would be a stupendously painful enterprise.
I am looking to write a React-Native application. I want to be able to download new modules at run-time on the device to extend functionality. There would be some core logic that knows how to request new modules based on some form input like a dbs. I do not want to bundle everything into a single monolithic bundle which is what I believe happens now with the built in packager.
This would something similar to how RequireJS works in browser. What I need to know is:
How do I build independent modules? react-native bundle doesn't seem to allow me to select which root modules to begin with and only works on root project
How can I at run-time request new functionality be injected into the current JavaScript environment?
React native starts by pointing at a JS bundle. This means that you would at least have to restart the app to reload the js bundle (assuming that you're reading it from a server and not from the ios device itself).
If you did have a way to update the js files on the server (through some sort of web service that updated based on things the user does) then restarting the app could theoretically reload the JS and provide new functionality to the app.
I was able to get something pretty close to this in JS only. First I had to expose a few more options in the current react-native bundler, mainly, the url (to change the "main" module) and blacklist (to keep from bundling react-native in second bundle) options to their packager (http://github.com/facebook/react-native/blob/master/packager/README.md).
I then had to write a custom fetcher that would download the second bundle and use eval() to evaluate it in the current environment.
The one rub is that I had to add __d('react-native',[],require('react-native')) in the first bundle which I think work like define() from require.js. This exports 'react-native' as an unmangled name that the modules which I plug in can access via normal require() statements. It's a bit confusing at first but from what I can tell they React-native packager works a little like r.js (see http://requirejs.org/docs/optimization.html).
I am very new to Node.js (which I'm assuming this is; I'm so new that I'm not really understanding what's going on here). I'm working with a client library for a system called RJ Metrics. I'm basically tying their API in with a Volusion API in order to import data into their system from the Volusion site. The code for that all makes sense but I'm not understanding how to install it and use it.
Their documentation is here:
And I'm needing to use the Javascript library because I'm working with Volusion which is on a Windows server and there is no ASP/C# option here. It says The RJMetrics Javascript client library is available via npm: and then terminal code. After research, it appeared that this uses Node.js so I installed that on my computer and ran the npm install rjmetrics in the Terminal which succeeded. I was assuming though that I must have to log into their server and run the code in order to get it to work.
Does this require me to SSH into the server? Am I way off base and is there a way I can just include some JS files in my page? I looked at their GitHub too and all of the main files use the require() function in them which I'm gathering is a Node.js function?
Apologies if I'm way off, I'm into this up to my neck and just trying to sort it all out now.
This part of the documentation (to which you refferred) is just plain ol' javascript. though NPM is the node package manager. So if you want, it looks like you can just run this .js script in a web browser like any other.
var rjmetrics = require("rjmetrics");
client = rjmetrics.Client(api_key, client_id);
# do stuff with client
If you wanted to do it in Node, you would create a .js file on your machine with their API code inside of it doing whatever you want. Then in terminal you run the script by going "node myfile.js". A local webserver setup is all you need to create and test this.