intro

场景1:

如果你发现有一个旧的meteor项目的版本是1.8.1的,是在2019年5月前创建的

你现在2021年10月,还想创建一个1.8.1的meteor项目,可以通过指定版本号来创建项目,如下:

​meteor create vue-meteor-app --release 1.8.1​

然后:

但是当你创建好项目,想通过在命令行输入​​meteor​​来运行时,发现报错了。

Uncaught Error: jQuery not found

他说你缺少jquery这个包,而且你不能通过​​npm i jquery​​来安装

而必须通过​​meteor add jquery​​这个命令来添加jquery这个包

meteor add jquery

好的,现在项目能正常运行了。

场景2:

但是当你信心满满地按照官网的文档,在meteor中集成vue框架时,发现又报错了

While loading plugin ​​vue-component​​ from package ​​akryum:vue-component​​: Cannot find module

你就会想,项目版本一样都是1.8.1,步骤流程也是按照官网来的,为什么2019年创建时就可以,而现在2021年创建就不行了呢?到底哪里改变了。

后来发现,原来是安装vue转换必备插件​​akryum:vue-component​​的时候,版本发生改变了。

通过查看2019年的旧项目
项目根目录/.meteor/versions文件
发现akryum:vue-component@0.14.3

另一个

通过查看2021年的新创建的项目
项目根目录/.meteor/versions文件
发现akryum:vue-component@0.15.3

结论:是插件版本发生改变了。0.14.3才能搭配1.8.1使用的,若是0.15.3就会报错。因此指定版本安装插件即可。

meteor add akryum:vue-component@=0.14.3

更多cmd命令,可以通过​​meteor add --help​​查看

到此时,在meteor中集成vue框架就成功了。

后面就跟着官网的步骤操作即可。感慨良多!

Integrating Vue With Meteor

To start a new project:

meteor create vue-meteor-app --release 1.8.1

To install Vue in Meteor, you should add it as an npm dependency:

meteor npm install --save vue

To support ​​Vue’s Single File Components​​ with the .vue file extensions, install the following Meteor package created by Vue Core developer ​​Akryum (Guillaume Chau)​​.

meteor add akryum:vue-component

如果项目运行不起来,应该是​​akryum:vue-component​​的版本和项目的版本1.8.1不搭配。

因此要指定​​akryum:vue-component​​的版本安装即可,如下:

meteor add akryum:vue-component@=0.14.3

You will end up with at least 3 files:

  1. a ​​/client/App.vue​​ The root component of your app
  2. a ​​/client/main.js​​ Initializing the Vue app in Meteor startup
  3. a ​​/client/main.html​​ containing the body with the #app div

We need a base HTML document that has the ​​app​​ id. If you created a new project from ​​meteor create .​​, put this in your ​​/client/main.html​​.

<body>
<div id="app"></div>
</body>

You can now start writing .vue files in your app with the following format. If you created a new project from ​​meteor create .​​, put this in your ​​/client/App.vue​​.

<template>
<div>
<p>This is a Vue component and below is the current date:<br />{{date}}</p>
</div>
</template>

<script>
export default {
data() {
return {
date: new Date(),
};
}
}
</script>

<style scoped>
p {
font-size: 2em;
text-align: center;
}
</style>

You can render the Vue component hierarchy to the DOM by using the below snippet in you client startup file. If you created a new project from ​​meteor create .​​, put this in your ​​/client/main.js​​.

import Vue from 'guide/site/content/vue';
import App from './App.vue';
import './main.html';

Meteor.startup(() => {
new Vue({
el: '#app',
...App,
});
});

Run your new Vue+Meteor app with this command: ​​NO_HMR=1 meteor​

Using Meteor’s data system

One of the biggest advantages of Meteor is definitely it’s realtime data layer. It allows for so called full-stack reactivity and ​​optimistic UI​​ functionality. To accomplish full-stack reactivity, Meteor uses ​​Tracker​​. In this section we will explain how to integrate Meteor Tracker with Vue to leverage the best of both tools.

  1. Install the ​​vue-meteor-tracker​​ package from NPM:
meteor npm install --save vue-meteor-tracker

Next, the package needs to be plugged into Vue as a plugin. Add the following to your ​​/client/main.js​​:

import Vue from 'vue';
import VueMeteorTracker from 'vue-meteor-tracker'; // import the integration package!
import App from './App.vue';
import './main.html';

Vue.use(VueMeteorTracker); // Add the plugin to Vue!

Meteor.startup(() => {
new Vue({
el: '#app',
...App,
});
});

Example app

If you’ve followed the ​​integration guide​​, then your Vue application shows the time it was loaded.

Let’s add some functionality that makes this part dynamic. To flex Meteor’s plumbing, we’ll create:

  1. A ​​Meteor Collection​​ called ​​Time​​ with a ​​currentTime​​ doc.
  2. A ​​Meteor Publication​​ called ​​Time​​ that sends all documents
  3. A ​​Meteor Method​​ called ​​UpdateTime​​ to update the ​​currentTime​​ doc.
  4. A ​​Meteor Subscription​​ to ​​Time​
  5. ​Vue/Meteor Reactivity​​ to update the Vue component

The first 3 steps are basic Meteor:

  1. In ​​/imports/collections/Time.js​
Time = new Mongo.Collection("time");

  1. In ​​/imports/publications/Time.js​
Meteor.publish('Time', function () {
return Time.find({});
});

  1. In ​​/imports/methods/UpdateTime.js​
Meteor.methods({
UpdateTime() {
Time.upsert('currentTime', { $set: { time: new Date() } });
},
});

Now, let’s add these to our server. First ​​remove autopublish​​ so our publications matter:

meteor remove autopublish

For fun, let’s make a ​​settings.json file​​:

{ "public": { "hello": "world" } }

Now, let’s update our ​​/server/main.js​​ to use our new stuff:

import { Meteor } from 'meteor/meteor';

import '/imports/collections/Time';
import '/imports/publications/Time';
import '/imports/methods/UpdateTime';

Meteor.startup(() => {
// Update the current time
Meteor.call('UpdateTime');
// Add a new doc on each start.
Time.insert({ time: new Date() });
// Print the current time from the database
console.log(`The time is now ${Time.findOne().time}`);
});

Start your Meteor app, your should see a message pulling data from Mongo. We haven’t made any changes to the client, so you should just see some startup messages.

meteor

  1. and 5) Great, let’s integrate this with Vue using ​​Vue Meteor Tracker​​ and update our ​​/client/App.vue​​ file:
<template>
<div>
<div v-if="!$subReady.Time">Loading...</div>
<div v-else>
<p>Hello {{hello}},
<br>The time is now: {{currentTime}}
</p>
<button @click="updateTime">Update Time</button>
<p>Startup times:</p>
<ul>
<li v-for="t in TimeCursor">
{{t.time}} - {{t._id}}
</li>
</ul>
<p>Meteor settings</p>
<pre><code>
{{settings}}
</code></pre>
</div>
</div>
</template>

<script>
import '/imports/collections/Time';

export default {
data() {
console.log('Sending non-Meteor data to Vue component');
return {
hello: 'World',
settings: Meteor.settings.public, // not Meteor reactive
}
},
// Vue Methods
methods: {
updateTime() {
console.log('Calling Meteor Method UpdateTime');
Meteor.call('UpdateTime'); // not Meteor reactive
}
},
// Meteor reactivity
meteor: {
// Subscriptions - Errors not reported spelling and capitalization.
$subscribe: {
'Time': []
},
// A helper function to get the current time
currentTime () {
console.log('Calculating currentTime');
var t = Time.findOne('currentTime') || {};
return t.time;
},
// A Minimongo cursor on the Time collection is added to the Vue instance
TimeCursor () {
// Here you can use Meteor reactive sources like cursors or reactive vars
// as you would in a Blaze template helper
return Time.find({}, {
sort: {time: -1}
})
},
}
}
</script>

<style scoped>
p {
font-size: 2em;
}
</style>

Restart your server to use the ​​settings.json​​ file.

meteor --settings=settings.json 

Then refresh your browser to reload the client.

You should see:

  • the current time
  • a button to Update the current time
  • startup times for the server (added to the Time collection on startup)
  • The Meteor settings from your settings file

Excellent! That’s a tour of some of Meteor’s features, and how to integrate with Vue. Have a better approach? Please send a PR.

Style Guide and File Structure

Like code linting and style guides are tools for making code easier and more fun to work with.

These are practical means to practical ends.

  1. Leverage existing tools
  2. Leverage existing configurations

​Meteor’s style guide​​ and ​​Vue’s style guide​​ can be overlapped like this:

  1. ​Configure your Editor​
  2. ​Configure eslint for Meteor​
  3. ​Review the Vue Style Guide​
  4. Open up the ​​ESLint rules​​ as needed.

Application Structure is documented here:

  1. ​Meteor’s Application Structure​​ is the default start.
  2. ​Vuex’s Application Structure​​ may be interesting.

SSR and Code Splitting

Vue has ​​an excellent guide on how to render your Vue application on the server​​. It includes code splitting, async data fetching and many other practices that are used in most apps that require this.

Basic Example

Making Vue SSR to work with Meteor is not more complex then for example with ​​Express​​. However instead of defining a wildcard route, Meteor uses its own ​​server-render​​ package that exposes an ​​onPageLoad​​ function. Every time a call is made to the server side, this function is triggered. This is where we should put our code like how its described on the ​​VueJS SSR Guide​​.

To add the packages, run:

meteor add server-render
meteor npm install --save vue-server-renderer

then connect to Vue in ​​/server/main.js​​:

import { Meteor } from 'meteor/meteor';
import Vue from 'vue';
import { onPageLoad } from 'meteor/server-render';
import { createRenderer } from 'vue-server-renderer';

const renderer = createRenderer();

onPageLoad(sink => {
console.log('onPageLoad');

const url = sink.request.url.path;

const app = new Vue({
data: {
url
},
template: `<div>The visited URL is: {{ url }}</div>`
});

renderer.renderToString(app, (err, html) => {
if (err) {
res.status(500).end('Internal Server Error');
return
}
console.log('html', html);

sink.renderIntoElementById('app', html);
})
})

Luckily ​​Akryum​​ has us covered and provided us with a Meteor package for this: ​​akryum:vue-ssr​​ allows us to write our server-side code like below:

import { VueSSR } from 'meteor/akryum:vue-ssr';
import createApp from './app';

VueSSR.createApp = function () {
// Initialize the Vue app instance and return the app instance
const { app } = createApp();
return { app };
}

Server-side Routing

Sweet, but most apps have some sort of routing functionality. We can use the VueSSR context parameter for this. It simply passes the Meteor server-render request url which we need to push into our router instance:

import { VueSSR } from 'meteor/akryum:vue-ssr';
import createApp from './app';

VueSSR.createApp = function (context) {
// Initialize the Vue app instance and return the app + router instance
const { app, router } = createApp();

// Set router's location from the context
router.push(context.url);

return { app };
}

更多资料请看meteor官网​​https://guide.meteor.com/vue.html​