Will JQuery and Underscore be Removed from Meteor?

Are these two packages slated to be removed from Meteor now that they are seemingly unneeded or have they been baked in to the project to such a degree that is a major refactoring of the codebase?

I’m just wondering cause 10 percent of my client bundle is Jquery and I am not explicitly using it anywhere in my code (and i know it could be used in packages I am using so I am not surprised its there just want it to go away haha)

1 Like

jQuery is not being removed from Meteor. They did a big update for changing jQuery from running as a Meteor package to the npm package (this way everyone can have the most updated version of jquery). There are some old meteor packages that still use old jquery versions like twbs:bootstrap but if you do the correct upgrade you will use the latest npm jQuery package for your project.

The latest release dropped jquery from the default packages list.
AFAIK you only need it for Blaze

underscore has been an ongoing major refactor, which has been removed from client-side code of meteor-base packages, so if you create a new project and remove blaze, you shouldn’t get underscore in your client bundle

1 Like

awesome … let me try that out

run meteor list --tree to see which packages are pulling in underscore
It’s still used by a lot of popular pacakges


do you know the command to remove blaze? or can i just remove this line from my packages file?

blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views

well removing that from the packages file wont allow my index.html to load properly … so im thinking thats needed … for now

Have you tried meteor add static-html?

I’ve managed to remove jQuery from my Vue project, but still have underscore.

if i remove blaze-html-templates and add static-html i am still unable to get that html to file to load in my client entry point where i create my root Vue instance. but i am sure I am just unfamiliar with how to configure things properly and just need to work through it. Thanks for the suggestion :slight_smile:

I haven’t spent that much time since starting to play with meteor on things of this nature. I wish there was more documentation of Meteor as a build tool and how it works in that capacity.

found it https://guide.meteor.com/build-tool.html :slight_smile:

Hi @brianmulhall, did you get this sorted out?

Where is your index.html file located? Mine is in /lib/ui/index.html because it is also used for SSR, but before SSR I had it in /client/ui/index.html.

yea i have it in my client folder. my client folder is just two files … main.html and main.js. main.js loads in main.html but it fails without this package blaze-html-templates package loaded

Looking at the readme for static-html it says it only pulls in the <head> and <body> blocks - does your main.html have those blocks?

The html file should not need to be loaded by main.js, if it’s in your client folder then static-html should pull it in automatically. Try removing that import.

If you still can’t get it working then I’m happy to have a go if you’re willing to share the source with me… You have my assurance of complete confidentiality, or happy to sign an NDA if you want.

yea it has a head and body section. My main.js file is where my root vue instance is made and then i load in the main.html to the main.js … do i need to do that?

import ‘./main.html’;

is that necessary to have my root vue instance refer to the app element by id?

when i comment it out, the html never loads.

Here’s my Vue setup:

// client/main.js ==================================

import CreateApp from '../imports/ui/CreateApp';

Meteor.startup(() => {
	global.app = CreateApp().app;

// imports/ui/CreateApp ================================

import Vue from 'vue';
import VueMeteorTracker from 'vue-meteor-tracker';

import App from './App.vue';
import router from './router.js';

Vue.config.productionTip = false;

function createApp () {
  return {
    app: new Vue({
      el: '#app',

export default createApp
// lib/ui/index.html ==============================

  <!-- the usual header stuff -->
<div id="app"></div>

The only reason CreateApp is in its own file in the imports folder is because it is also used by SSR, but if you don’t need SSR you can include all that within client/main.js.

At no point do I import the index.html file, static-html does that automatically.

Does calling it index.html instead of main.html make any difference?

1 Like

hey that did it :slight_smile:

1.) remove blaze-html-templates from the packages file
2.) add static-html (meteor add static-html)
3.) remove the import ‘./main.html’ from main.js

but i needed that import when static-html wasn’t installed and the blaze-html-templates was. Thanks for helping me out. Now i want to check out my client bundles size haha. I’m down from 940 KB to 720 KB uncompressed

Im down to 637 KB … not bad

Has jQuery gone from your client bundle?

You inspired me to look again at my bundle size yesterday. I found only one client package was using underscore, and only for some very simple _.isString() checks. I forked that and re-wrote it to remove underscore and saved… 15kB (5kB gzipped) from my client! Hardly worth the effort, but every little helps :wink:

Dynamic importing your routes is the biggest saving.

Also, if you use Optimistic UI (Meteor.methods shared between client and server), then you can make each component (or route) only import the methods it needs. Then your initial bundle doesn’t contain all the unnecessary methods. This might mean moving the method files out of /lib and into /imports/, and then you have to manually import them all into the server.

I think 720KB is pretty good though, well done!

Yea JQuery is gone now … and that was what kind of started this whole thing haha. 10% of my client bundle (back in the days of a client bundle that was 930KB) was too much. But Underscore is only 2% (15KB in size like you said) at the moment, so I am not sure if I am going to worry too much about it.

But I do like working through things … just to get my head around how it works. And to get used to the tools i need to solve problems when they come up in the future. The bundle-visualizer is great. I love that thing

Also, I came up with a trick to prevent importing cordova-specific code into my web app:

// imports/ui/App.vue:
  <cordova-imports v-if="$options.isCordova" />

export default {
  components: {
    cordovaImports: () => import('../cordova/imports.js')
  isCordova: Meteor.isCordova, // this is available as $options.isCordova and is non-reactive.
  data() { return {

// imports/cordova/imports.js
import './pushNotifications.js'
import './geolocation.js'
1 Like

I havn’t gotten my application running on an android since I ported it over from Blaze to Vue, but I am working towards that. I just finished up the Accounts management code and components, and now I am working on the Roles management components. With a couple detours checking out SSR and Svelte for a bit. But I am really excited for 1.10 release and the focus it places on Cordova. So i will try out the code you posted soon. Thank you

@wildhart can ask you a few questions about how you use Vue and Meteor?

Do you use Session, ReactiveVar or ReactiveDict in your apps? or do you just wrap Meteor’s prebuilt reactive data sources in tracker.autorun statements that will reassign any updated value to a data field on the vue instance and then let Vue reactivity take over? Like for instance I do this with my userId and when i log in and log out my Vue instance’s data field will get updated and then that value with drive UI updates. do you do the same thing?

I use vue-meteor-tracker. Then you don’t need Session, ReactiveVar or ReactiveDict at all. That package basically wraps meteor’s reactive data sources inside tracker.autorun inside Vue’s computed properties. Very clever.

For example:

  <div v-if="userId">
    <div>Your name: {{currentUser.profile.name}}</div>
    <threads-component :threads="threads" />
  <login v-else />

export default {
  meteor: {
    $subscribe: {
      'threads': [] // subscribe to all threads for this user
    userId() {
      return Meteor.userId();
    currentUser() {
      return Meteor.user();
    threads() {
      // from 'users' publication
      // this will return a live cursor which will automatically become a reactive array within Vue
      return threadsCollection.find();

This is obviously a simplified example. In reality you might query the threads collection within the threads component, but you get the idea.