requiring packages with JS instead of the asset pipeline - Rails - javascript

I'm trying to use a plugin called simplemde I used bower to bring in the plug in. The javascript it imported is trying to require other addons but when I try to run the code I get this error in the console Uncaught ReferenceError: require is not defined. I understand the you cannot require from the client side unless you make changes to the asset pipeline. I'm trying to find out what to do in this situation with a rails app.
JS
var CodeMirror = require("codemirror");
require("codemirror/addon/edit/continuelist.js");
require("./codemirror/tablist");
require("codemirror/addon/display/fullscreen.js");
require("codemirror/mode/markdown/markdown.js");
require("codemirror/addon/mode/overlay.js");
require("codemirror/addon/display/placeholder.js");
require("codemirror/addon/selection/mark-selection.js");
require("codemirror/mode/gfm/gfm.js");
require("codemirror/mode/xml/xml.js");
What are some ways I can get this file to work with Rails?

I bet you use files from the src directory of the SimpleMDE plugin. This files should be preprocessed and assembled into one on the server side before delivering to the client. You can use minified and assembled files from the dist directory. If you want to use source files anyway, you should tune your asset pipeline, for example like in article Bring CommonJS to your asset pipeline or use other tools, like Grunt or Gulp, for assets assembling.

Related

How can I use a module from npm in a django-admin widget, without installing node?

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.

Webpack 2: Watch external files

I have a project that uses source files external to the project. Effectively, there is the actual project source code (an Typescript/Angular 2 application, lets call it the 'core' stuff), and this is a generic web application that is meant to be the base code that consumes these external source files.
The external files include additional stuff-- that could be SCSS files, images, evn additional JS. The way I want this to work is that webpack copies these external files from any source directory (this is critical, it is not part of the core project) to a local .tmp directory. The files in the .tmp directory are worked on along with the core src files to generate the prod output.
I can't figure out how to add these additional external source files to the watch list. Effectively what I'm looking to do is watch that directory and as things change, it re-copies the affected files to the local .tmp directory and triggers a recompile.
Presently I have to restart webpack and have a very very ugly solution using Grunt to watch the additional files. It's nasty but these kinds of workarounds have historically been what I've had to do with webpack.
Does anyone have a better solution? Ideally I'd like to not have to mix grunt with webpack. Webpack should be able to do this, but its hard to know whether there's an existing plugin for this or what the best approach would be.
Also, please spare the "look for it on google" or "read the docs" comments. I've combed through it all, hard, and have not found anything.
Thanks in advance.
As of now Webpack doesn't watch external files out-of-the-box . You need a plugin for that.
Basically idea is to have a file watcher module chokidar / watch , listening to the file change , and when there is a change, restart the webpack compilation phase . Webpack plugins can access the compilation object and we you need to hook it to a compiler phase i.e. 'emit' , 'after-emit' etc.
This Webpack plugin exactly solves your problem - https://www.npmjs.com/package/filewatcher-webpack-plugin .

Loading prebuilt webpack bundles at runtime

Is it possible to require dynamic bundles at runtime with webpack? Let assume I have two separate bundles from two separate builds and I want to load modules from one bundle into another at runtime, dynamically without knowing during compilation which bundle and at what path this bundle would exist. It could be another file in directory or file from cdn.
To be detailed, prebuilt library exports something like this:
export default { Component, someFunction, otherFunction }
Every library has the same format and server provides information about path to this library at runtime. I'm thinking about something like
pathToBundle = "http://cdn" or "/bundles/name.js"
import(pathToBundle).then(module => {}).catch(error => {})
Whole gimmick is loading prebuilt bundles that are dynamically defined. I know I can do similar thing but I have to know bundles at runtime or even build them during the same bundling process and split as separate chunks.
My inspiration is Atom plugin system but for web without file system and Node context as Atom has. I have full access to server so anything server can do over http/ws could work.
I was initially thinking about something like webpack-dev-server but I don't want to rebuild whole application. My goal is to eliminate Node runtime dependency at server because I'm using other backend language for that right now and only provide already built bundles.

Adding javascript files to Yeoman webapp generated website

I am playing with the yoman trying to build a web site using the webapp generator.
If Managed to create a web site that works under grunt server, when I change a js file grunt notices the change change and does a live load and everything works as you would expect.
When I try a plan grunt, it attempts to run the dist task, it manages to include my html files, but skips any of the javascript or script files I created in the script and styles diretores. I assume its the case I have to tell grunt to includes these files
Files such as main.js seem to make it through, but there are no references to main.js in the Gruntfile, so I not sure which part of Gruntfile.js to change.
Doing a yo doctor reports
[Yeoman Doctor] Everything looks all right!
Q. How to do I tell grunt to include and user created files.
Q. I noticed that all my image files where renamed, fair enough how do I refer to a file that I known is going to be renamed in a javascript file
Q. Does anybody known a good web resource for yoman where these quesion might have already been answered?
Be careful on this glob pattern scripts/{,*}/*.js. This takes only the js files that are inside scripts or immediate child folders.
Make sure to change it to scripts/**/*.js to include all js files in all subfolders.
Also get an idea on tags build: css, build: js in your index.html, wiredep plugin used by Yeoman in gruntfile to understand what files will be injected into dist folder.

Include external JS in Rails asset pipeline that gets bundled during deploys

I reviewed this question already - Including external libraries using the Rails 3.1 asset pipeline - which is basically what I'm looking for with one caveat: I'd like to include the external url in the asset pipeline so that when I deploy to production, the external url gets bundled into a file with the other local files that were required.
More details:
My use case here is that I have found a plugin on GitHub that I like, and being a good member of the open source community, I'd like to help contribute back. The most time efficient technique that I'm considering is to fork the repo, then point my local project that needs that file to the raw source of the required JS file during development, but have that file get bundled with the rest of my application when I deploy to staging / production. This would allow me to keep the plugin tied closely to the parent project, but keep things on my own track so that I can decide when to merge in updates from the base project as well as submit any fixes I have back to the parent with easy pull requests.
With that said, I have not been able to find any documentation about how to do this with the current rails JS asset pipeline or if it is possible at all. Some quick tests locally point to the idea that this works in a css file but not for js files. Can anyone confirm if this is possible? Thanks!
I would use something like this custom rake task. Basically what you do is write that rake task into the beginning of your deploy script, but modified to put the file in your vendor/assets folder (or where ever you want that is pulled into the asset pipeline.)
That way you pull the requested file on deploy, but it's there in your code when your asset pipeline bundles everything up.
Here is the code in-case the link rots:
namespace :remote_file do
desc "Get a file from a remote server"
task :fetch do
# based on http://snippets.dzone.com/posts/show/2469
# http://farm1.static.flickr.com/92/218926700_ecedc5fef7_o.jpg
Net::HTTP.start("farm1.static.flickr.com") do |http|
resp = http.get("/92/218926700_ecedc5fef7_o.jpg")
open("fun.jpg", "w") { |file| file.write(resp.body) }
end
end

Categories