Nextcloud-vue: Moment

Created on 4 Sep 2018  路  17Comments  路  Source: nextcloud/nextcloud-vue

As discussed at https://github.com/nextcloud/vue-components/issues/9#issuecomment-415686834, I'd like to see a component for the moment.js integration, a.k.a. x seconds/minutes/hours ago thingy.

The existing Vue components suggested didn't work as expected, esp. in regards to l10n. Moreover, they wouldn't work with our live timestamp update magic (cc @nickvergessen). Hence, I've created my own component. This is what it looks like:

<template>
    <span class="live-relative-timestamp"
          :data-timestamp="timestamp"
          :title=title>{{ formatted }}</span>
</template>

<script>
    import moment from 'moment';

    if (typeof OC !== 'undefined') {
        moment.locale(OC.getLocale());
    }

    export default {
        name: "Moment",
        props: [
            'timestamp',
            'format'
        ],
        computed: {
            title () {
                return moment.unix(this.timestamp / 1000).format(this.format || 'LLL');
            },
            formatted () {
                return moment.unix(this.timestamp / 1000).fromNow();
            }
        }
    }
</script>

It works well and can be easily integrated. The live updating also seems to work with this.

Caveats

  • Pulls in moment.js (obviously) but also lots of translations. Webpack combines some stuff, but it's still rather big. We basically have the same problem in server, but we'd now load the locals twice.
  • Depends on a global var. I've added a check for it's existence, though.
2. developing component

Most helpful comment

On you entry file:

// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)

// Correct the root of the app for chunk loading
// OC.linkTo matches the apps folders
// OC.generateUrl ensure the index.php (or not)
// eslint-disable-next-line
__webpack_public_path__ = OC.generateUrl(OC.linkTo('contacts', 'js/'))

Webpack config:

    output: {
        [...]
        chunkFilename: 'chunks/[name].js'
    },
    [...]
    plugins: [
        [...]
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ],

Babel config

{
    [...]
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

Then just import

    import('moment/locale/' + this.locale)
        .then(e => {
            // success
        })
        .catch(e => {
            // failure
        })

All 17 comments

How big is big? As we cache JS stuff pretty agressively.

How big is big? As we cache JS stuff pretty agressively.

~1/4 MB according to https://github.com/jmblog/how-to-optimize-momentjs-with-webpack#measurements.

1/4 like 0.25 or 1-4MB? ^^

1/4 like 0.25

250kB :D

For a component that only display a relative date, this is crazy ^^"
If we only display by units like x sec ago x days ago x hours ago, shouldn't this be universal across languages?

For a component that only display a relative date, this is crazy ^^"

Yes, kind of. But the main lib is tiny. It's just the translations that make it a huge bundle of small packages that, apparently, sum up a lot.

If we only display by units like x sec ago x days ago x hours ago, shouldn't this be universal across languages?

I doubt it. We would have to provide our own translations.

So I'd simply go with the slighly oversized moment.js now and we can always replace the underlying library if we find a replacement. Users of the component wouldn't and shouldn't notice.

We could use the t() function like we do everywhere?

We could use the t() function like we do everywhere?

But then we'd have to translate all moment strings ourselves. If we go with the existing package, it already has all the translation strings.

Again, let's start with something simple (existing, big momentjs thingy) and we can always replace that by our own code. To make progress, I'd like to keep things as simple as possible now.

Is there that many translations needed? I mean, it's like any other translation son our website?

the thing is, this will be included like 10 times in the end?
activity, notifications, announcements, talk, ...

Is there that many translations needed? I mean, it's like any other translation son our website?

Well Days in long and short (Mon. Monday), same for months (dec. december), etc.

But yeah im fine with a huge bump at the moment and fixing it properly afterwards

Looking at the moment lib, I'm pretty sure we can ship this with a dynamic load of the locale. So moment (48.9KB) + locale (avg 1.5KB) we should be fine.
But we need a proper webpack dynamic loading setup :)

Small references: alternative lib that does the same and is as supported: https://github.com/date-fns/date-fns/
More features and explanations: https://github.com/date-fns/date-fns/issues/275#issuecomment-264934189

And webpack reference for moment: https://webpack.js.org/plugins/ignore-plugin/#ignore-moment-locales

Small update, I successfully implemented moment into contacts.
With dynamic loading! :)
It works very nicely! I'll share the config soon :)

On you entry file:

// CSP config for webpack dynamic chunk loading
// eslint-disable-next-line
__webpack_nonce__ = btoa(OC.requestToken)

// Correct the root of the app for chunk loading
// OC.linkTo matches the apps folders
// OC.generateUrl ensure the index.php (or not)
// eslint-disable-next-line
__webpack_public_path__ = OC.generateUrl(OC.linkTo('contacts', 'js/'))

Webpack config:

    output: {
        [...]
        chunkFilename: 'chunks/[name].js'
    },
    [...]
    plugins: [
        [...]
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
    ],

Babel config

{
    [...]
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
}

Then just import

    import('moment/locale/' + this.locale)
        .then(e => {
            // success
        })
        .catch(e => {
            // failure
        })

Correction:

// We do not want the index.php since we're loading files
__webpack_public_path__ = OC.linkTo('contacts', 'js/')
Was this page helpful?
0 / 5 - 0 ratings

Related issues

nicolad picture nicolad  路  4Comments

raimund-schluessler picture raimund-schluessler  路  9Comments

jancborchardt picture jancborchardt  路  9Comments

szaimen picture szaimen  路  8Comments

korelstar picture korelstar  路  7Comments