Shimming dependencies of dependencies with browserify-shim - browserify

I'm trying to refactor a library that uses Browserify by shimming certain modules out of the bundle using browserify-shim. Specifically, the library uses require("codemirror") but I want to provide a bundle that doesn't include CodeMirror but will rather use one that is provided via CDN.
So I've got browserify-shim config in my package.json like
"browserify-shim": {
"jquery": "global:jQuery",
"codemirror": "global:CodeMirror"
}
So far so good. require('jquery') and require('codemirror') have disappeared from the browserified bundle and been replaced by the expected code snippet to grab jQuery and CodeMirror off of the window object.
The library also requires some CodeMirror add-ons. For example require('codemirror/addon/hint/show-hint.js'). That's fine. I want that add-on bundled. However, within this add-on is a UMD wrapper that includes require("../../lib/codemirror"). Browserify is seeing this and is bundling the CodeMirror from /node_modules/codemirror/lib/codemirror.js because of this (I think). I want this to use window.CodeMirror as defined in the codemirror shim instead, but cannot figure it out. Have tried many variations including the following:
"browserify-shim": {
"jquery": "global:jQuery",
"codemirror": "global:CodeMirror",
"../../lib/codemirror": "global:CodeMirror",
"codemirror/addon/hint/show-hint.js": {
"exports":null,
"depends":["../../lib/codemirror:CodeMirror"]
}
}
That require("../../lib/codemirror") will not go away! I'm sure I'm missing something.
I'm running this from a Gulp script, but I don't think that should make any difference. Browserify version 3.38.1. Browserify-shim version 3.7.0.
Any ideas?

If you add browserify-shim with {global: true}, it should be applied to your dependencies' dependencies (and so on) as well, which should hopefully do what you want.
Assuming you're using raw browserify in your Gulpfile, instead of:
b.transform('browserify-shim');
do:
b.transform({global: true}, 'browserify-shim');
If you're using gulp-browserify, I'm not sure whether there's any way to specify global transforms.

{global: true}
works for me... why is this not a default?

Related

vue-cli-service: SyntaxError: Unexpected token '...'. Expected a property name

I'm working on putting together a small app using vue, and I specifically need it to run on a device that does not support ES6. I'm using vue-cli-service build to build, and when trying to open this page on my ES5 device, I'm seeing this error SyntaxError: Unexpected token '...'. Expected a property name.
I have installed babel, and added this to my .babelrc: { "presets": ["#babel/preset-env"] }
I'm not really sure what else to try, I haven't been able to find anything that specifically addresses this. Even the vue-cli-service documentation suggests ways to support polyfill for ES5, but I don't think this is the same thing.
I had this problem with Vuetify and Safari 11.1
I guessed I needed to transpile the ES6 version of Vuetify for older browsers. The solution was difficult to search for, as most of the suggestions were about modifying webpack or babel configuration, which I find obscured inside Vue CLI.
I eventually uncovered the solution myself by rebuilding my project from scratch via Vue CLI, and the installer magically added a transpilation option for Vuetify which I was missing - I think because I had previously upgraded Vuetify across the ES5 to ES6 versions, and perhaps their upgrade script doesn't perform this step.
vue.config.js
module.exports = {
"transpileDependencies": [
"vuetify"
],}
this is the equivalent of webpack
build: {
transpile: ['vuetify']
}
Restart the build and reload.
Of course you will need to find which of your packages it is - this is just an example. I just dug around in the error stack until finding something which belonged to Vuetify.

vue-cli build not using minified versions of libraries

I am trying to reduce the size of my SPA build, which gets build using vue-cli build. I am using Chart.js and after building the application, I ran webpack-bundle-analyzer and it shows Chart.js with it's full size, and not chart.min.js.
What I am expecting is that it would use /dist/chart.min.js. I am not understanding this correctly, or is it actually using the non-minified file?
I got around to having another look at this and this is simply because vue-chartjs needs chart.js as peer dependency and is thus not taking care of anything in my side of the build step.
Related: https://github.com/apertureless/vue-chartjs/issues/249
The fix is to configure it accordingly in the webpack config:
resolve: {
alias: {
'chart.js$': 'chart.js/dist/Chart.min.js',
},
},

How to access npm-installed package in hexo app

I am creating a web app using Hexo. I want to use a package called slick-carousel in one of my pages. This package also contains jQuery by the way. So I successfully installed (and "--save"ed) the package via npm. The package shows up in my node_modules folders and on my package.json file.
I expected that after doing this, I should have access to both jQuery and slick functions in my markdown files, but I don't. When I render the generated page on my browser, I am told that 'jQuery is undefined.' What step am I missing here so that I can actually use my installed packages?
Here is the script tag I added to my markdown file that I am trying to make work:
<script>
jQuery(document).ready(function(){
jQuery('.carousel').slick({
dots: true,
infinite: true,
speed: 300,
slidesToShow: 1,
centerMode: true,
variableWidth: true
});
});
</script>
I am still trying to fully grasp the relationship between installed packages and the rest of my application, so forgive me if this question doesn't even make sense. Any insight or explanation you can give me would be much appreciated!
Just because the scripts are in node_modules, doesn't mean they are automatically added to your projects frontend.
There are different ways to achieve what you need:
Manually moving the assets
Instead of trying to fiddle around with package.json and module requirements, the probably easiest way to get what you want is
moving the distribution files of jquery and slick-carousel out
of the node_modules folder into a folder where Hexo can work with
them better (after a quick read-up it should be source) then you
just link your JS file in your HTML layout and everything should work fine
Automatically moving the assets
With using some kind of task toolkit (like Gulp or Grunt) you could write tasks that automatically move the assets out of the node_modules folder inside a folder that is accessible by Hexo, a Gulp task could look something like this:
gulp.task('jquery', function () {
return gulp.src('./node_modules/jquery/dist/jquery.js')
.pipe(gulp.dest('./source/js'))
})
Using require (if supported)
I never used Hexo before, so I have no idea of it's internals, but sometimes it might be possible to just use require in the Javascript files to load modules that were downloaded, so you could use
window.jQuery = window.$ = require('jquery')
for example, to directly load the script as module.
You might need to test this yourself, but these are probably the three most common ways to handle assets in Node.js projects.

How to use browserify with non-npm libraries?

According to http://www.slant.co/topics/1089/viewpoints/1/~what-are-the-best-client-side-javascript-module-loaders~browserify#9 one of the downside of using Browserify is that:
Not all javascript libraries have an npm version
While it's not too hard to create npm package for an existing library, it means maintaining it when the library updates. While most libraries are now on npm, many client side specific libraries are not.
I don't have any experience with npm aside from knowing how to install an existing module. In light of that, what is the easiest/best way to browserify with client-side non-npm libraries?
Is there a way for me to declare a local Javascript file as a dependency, instead of looking it up through npm?
You can use local modules without problems by two ways:
1.Use a relative path to a module in require:
var myModule = require('../js/my-module');
2.Use a module name, but before, you should to add it to browser property in package.json:
package.json:
...
browser: {
my-module: './js/my-module.js'
}
app.js:
var myModule = require('my-module');
Some packages are packages with bower, these can be used with browserify by using the debowerify plugin.
For non-versioned things you can copy them to a lib directory in your project or add them as a git submodule and then configure browserify so that it can find things there too.

How to load a bootstrap js file in my case?

I have a question regarding loading the dependencies using Bower.
I have bower.json like
{
"name": "My project",
"version": "0.1",
"dependencies": {
"angular": "~1.2.0",
"angular-bowser": "~0.0.1"
}
}
//I want to add alert.js dependency
I was hoping to add a custom bootstrap JS file that is only for alert. I am not sure how to add the custom file since I can't run bower install to install the custom file.
Any tips? Thanks a lot!
You add bootstrap as a Bower dependency. Then in whatever other tool you're using to either generate <script> tags or generate a single concatenated JS file, you add Bootstrap's alert.js (and any other Bootstrap jQuery plugins that Alert depends on) to the list of required JS files.
Speaking more generally, Bower is an pretty minimalistic package manager, to the point that it is arguably not very useful, as it provides relatively little metadata and leaves many issues to instead be dealt with by other tools or by the user manually. Hence, what you're asking for here goes beyond the realm of Bower itself.