I am trying to do all my package management with JSPM, and I would like in some cases for the bundled minifed version of a library to be loaded by SystemJS instead of each individual source files (and I don't want to do the bundling myself with the JSPM CLI).
For example, I am doing the following:
jspm install angular2
And then I have a small application based on Angular2. When I look at what happens on the network, the browser loads a whole bunch of files that are part of Angular2, although in this particular case I would like to use angular2.dev.js, which is part of the angular2 module installed by JSPM (and maybe in production I would like to load something else).
Is there a way to do this with jspm (basically to replace bower + a script tag)?
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.
I'm afraid this will be a stupid question. But I don't manage it to use my JS-Package (for example jQuery), which i have installed with Visual Studio Nuget-Package-Manage in my .net 5 Blazor Server-App.
What i did:
Installing the Package. Here I installed jquery.datatable which includes jQuery itself:
Image of my Project
But now, i don't know how to include it for example in my "_Host.cshmtl"-File:
<script type="text/javascript" charset="utf-8" src="???WHERE IS IT????"></script>
Where is my *.js-File? For example: query.dataTables.js ??
I found it on "C:\Users\xxxxx.nuget\packages\jquery.datatables\1.10.15" and
"C:\Users\xxxxxx.nuget\packages\jquery\1.7.0"
Do i realy have to copy it to my wwwroot-Folder manualy?
If so, why i should use the package-manager?
Thanks for your help!!
Traditional web applications using JavaScript normally load the file from a local folder or from a web CDN (e.g. CDNJS.com etc). This is then loaded from the page (often referenced from a layout file).
Early on it used to be the case that JS libraries could be loaded via NUGET packages but this approach is now discouraged. It had to fix the creation of the script in a set location, e.g. /Scripts and there was no flexibility. Almost all client-side libraries are now in NPM as packages or on CDNs like cdnjs.com.
The current approach for .NET web apps to load client-side assets is either use LibMan or NPM and have some sort of webpack arrangement to compile/pack/copy. You would never load the JS from a /packages folder in the way you suggested.
Blazor Approach
Blazor (since .NET 5.0) can load either embedded JS modules (from your code), or from a URL directly.
If you want to package some JS with your application you should look at Razor Component libraries. This allows static assets such as JS files to be embedded in the code, which Blazor makes available via the _content route, e.g.
_content/LibraryName/myfile.js.
Because Blazor is a SPA you don't include JavaScript using a <script> tag in your HTML, you should load it as a module and reference it there.
This documentation explains it:
https://learn.microsoft.com/en-us/aspnet/core/blazor/call-javascript-from-dotnet?view=aspnetcore-5.0#blazor-javascript-isolation-and-object-references
DataTables, JQuery
So should you include jquery.min.js and jquery.datatables.min.js in your library? I'd suggest a better approach is to load from a CDN - your package is smaller and there is a chance the URL is already cached and loaded, e.g.
var module = await js.InvokeAsync<IJSObjectReference>(
"import", "https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js");
This loads the module on-demand from the URL directly. You'd also need to load jquery before this.
Finally I'd make this observation: are you sure you want to go down this route?
There are several native Blazor libraries on NUGET for rendering and handling tables. You'll find it much easier to go this way rather than try to patch jquery-based libraries into a Blazor app.
I had a similar issue. Not with the same libraries, but I was wanting to do something that wasn't available in a Blazor library yet. I needed a video player that could handle a certain format that the default HTML 5 video element can't handle. There is an open source player, videoJS , that did the job, but it's a javascript library. It's available on npm and there are cdn's - however the plugins (as far as I could tell) weren't on CDN - so I had to go down the npm route.
When you install an npm package it puts it into a hidden node_modules folder. Unfortunately even if you point to that path or even copy the file in with your other js files it won't work. Npm packages are designed to be run by nodejs, rather than directly in the browser. In order for them to run in a Blazor app (in the browser) you have to do an intermediary step of transpiling it into a browser friendly format.
What I really wanted was a re-usable component, that wrapped the javascript.
It took me a while to get there but I finally figured it out. I've written a series of articles on my blog detailing it. The final one ports everything into a Razor Class library that can be consumed with no knowledge of the underlying js. The fourth article deals with importing npm libraries and using them within a web assembly app. I'll put the link below but essentially the process is:
Create a folder eg JS and initialise it for npm (npm init -y)
Install the required npm packages (npm install --save)
Create a src folder within the JS folder that that you will put your own js files in
Create an index.js file in src that imports the required javascript modules and exports what you want to consume
Install snowpack (npm install snowpack --save-dev) (or webpack but I found snowpack seems to work better)
Configure snowpack to process the contents of the src folder into wwwroot/js (without snowpack or similar the files in the npm package won't be in a browser or blazor useable format)
use javascript isolation to pick up your index.js file from wwwroot/js
See blog post here for full details (It's part 4 of a 5 part series - part five puts it all in a razor class library so you can add it to a project without ever seeing the javascript)
I know this is late but this SO question was one I kept coming across when searching on how to do what I wanted, so thought I'd put my solution here in case it helps anyone else searching for what I did.
I installed MathJax library for my site on ASP.Net Core from Package Manager.
I have seen 'MathJax (2.7.0)' in NuGet Dependencies:
Image of My Dependencies
But is it all. When I see wwwroot\lib directory in my project I don't see 'MathJax' folder or something similar in it:
Image of My fron-end lib
But when I need use MathJax I need write something similar in my html-page:
<script type="text/javascript" async src="~lib/MathJax/MathJax.js?config=TeX-AMS_HTML-full"></script>
I can't copy NuGet library directly in wwwroot\lib, because I don't want to add my git repository a lot of files external project (> 36 Mb, > 1500 files). Besides, why use NuGet then?
Also, I can't add existing items of MathJax NuGet library manually (menu Add -> Existing Item...), because they are a lot and the absolute path will not correctly on another PC.
How I can get correctly link on MathJax library in NuGet package?
The JavaScript/CSS library NuGet packages are not for Core. They're for MVC. ASP.NET Core has a completely different approach to static files and client-side libraries than ASP.NET MVC did.
For an ASP.NET Core site, you need to use either LibMan or npm to get your client-side libraries. LibMan is easier, but also very naive and limited. In particular, it only supports libraries that are on cdnjs. While there's a lot of coverage there, it's not comprehensive, and there's some libraries that just are available. I'm not sure whether your particular library is or not.
However, given that you'll almost inevitably end up needing something you can't get through LibMan, and and then you'll be forced to use npm anyways, you might as well just use npm and get used to it. There's more of a learning curve because you also need to create build tasks with something like Webpack, Gulp, Grunt, etc. The npm packages go into a node_modules folder, which should not be served directly. At the very least, you'll need to use Webpack, Gulp, etc. to copy the dist/build of the npm package (i.e. the actual JS/CSS files that you'll be referencing) into your wwwroot/lib directory. There's lots of guides online for how to set this up. Just do some research.
In the VS2019, go to the wwwroot/lib directory, right click and select Add -> Client-Side Library. then include your file.
Go to the web project, right click and go the manage client scripts, then search your library and instal.
I am exploring AngularJS tutorial project and found it has node_modules directory inside, which size if 60 megabytes.
Does simple clientside javascript project really need so huge corpus of unknown data?
I tried to delete this directory and project still works. I suspect it somehow relates with node.js and it's npm but how? Suppose I need to run my project on some conventional web server (not node.js), then how to know, which files/directories are unneeded?
Many javascript libraries require to use bower to install them. If I use bower, does this mean I need to keep node_modules?
The node_modules directory is only for build tools.
The package.json file in the app root defines what libraries will be installed into node_modules when you run npm install.
Very often with an angular app, on your dev machine or on a build server, you use other Javascript libraries from npm (a node.js package manager) to build your angular app. Tasks can be concatenating resources, using CSS preprocessors like LESS or SASS, minification, replacing of values, etc. etc. The most common tools for managing and running these tasks are called grunt and gulp, which are installed through npm as well.
When you deploy your app, you only distribute the resulting build, not any of the source files or build tools.
It is of course possible to write an AngularJS app without building anything.
edit from comments: When you dive into Angular more, there are more advanced techniques of using libraries installed by npm even in the client app, you then selectively choose the ones you need, not the whole 50MB+ thing. I'd recommend staying with the basic approaches until you get a good grasp on them though.
NPM is the node package manager, which installs packages locally into a project, specifically, into the node_modules folder. From there the package code can be included into a project, yes, can is the important word there.
The browser has no way to include modules in code (yet), so you need to use a library that can expose node's commonJS style modules. Browserify and Webpack are two popular methods of doing so.
Angular complicates this by introducing its own module system, which more closely resembles AMD-style modules. There are ways around this, so that you can use node-style modules, maybe your project uses those.
Using npm for managing dependencies is a great idea, its a fantastic package manager. It is likely in your case though that the project is only built using node and that the node_modules folder contains dependencies only related to the build.
If I have a directive, and I wish to package it in its own node package; and then include it from another another node package containing the main angularjs app, how would I do this?
My rough idea about how to go about this is:
put the html, javascript, and css for the directive in the package folder
enable compilation of these assets - preprocessing, minification (how?)
configure as bower package
in the app folder install the bower package
how to do this locally, without publishing?
in the angular.module() statement that creates the main app, add the name of the module containing the directive
Is this correct?
Have I missed out on anything?
Your idea of how to go about this looks good to me. To answer your questions in the list:
Look at Grunt or Gulp for your preprocessing / minification needs. These are both excellent build tools. Grunt is more widely used, but Gulp is newer and gaining a lot of ground. I'd look at both and use the one that suits you.
How to use a local bower dependency w/o publishing:
In your main app's bower.json file, instead of putting a version number for your module, put the folder where it can be found on your local system, like so:
{
"dependencies": {
"my-module": "/home/me/modules/my-module"
}
}
To clarify, you refer to it as a "node package" in your question, but in reality, you are creating a Bower package. Node packages (published to npmjs.org) are for node, and unless processed with something like Browserify, won't run in the browser (and even then, the node package can't do anything the browser doesn't support, like file access.) Bower packages (published on bower.io) are specifically for the browser. You will however find packages that publish to both NPM & Bower, such as jQuery or underscore, but you can't use the npm jquery package in the browser, it's built to run in node, and vice-a-versa.