Git Product home page Git Product logo

vue-script2's Introduction

VueScript2 - Simple, Familiar Asynchronous Script Loading

VueScript2 brings back the <script> tag to your SPA (Single Page App)!

This tiny library should take care of all your declarative and imperative asynchronous loading needs. Web designers can rest easy knowing their existing knowledge of web development is still useful!

This version is tailored for the Vue.js framework, but it's easy to port to Riot.js and others.

VueScript2 is primarily for internal use and not for standalone components that are being shared publicly. Those should be "self-contained" and come with all the JS they need.

NOTE: Requires Vue 2.x. Use version 1.2.2 for Vue 1.x.

Features

  • Just like <script> except with a 2, but even that can be fixed!
  • Keep your app.js bundle small!
  • Embrace Web Standards™ everyone knows and loves!
  • Easy for web designers to pick up! If you know HTML, you already know how to use it!
  • Tiny! Less than 1kb! (min+gzip'd)
  • Perfect for use in .ejs templates or .html files!
  • No more including every library on every page or complicated "code splitting"!
  • Ordered execution based on position in markup!
  • Special unload attribute can be used to keep your app's memory usage low!
  • Does imperative loading too!

Installation

npm install vue-script2 --save

Then enable the plugin (in your main.js or wherever):

Vue.use(require('vue-script2'))

Or with import:

import Vue from 'vue'
import VS2 from 'vue-script2'

Vue.use(VS2)

Usage

Note: you can write <script> instead of <script2> using script2ify! 😄

Familiar, declarative, asynchronous loading of scripts

Using vue-script2 with vue-router is simple. Say that only one of your routes displays a "page" that makes use of jQuery. Well, no need to include all of jQuery in your app.js bundle, now you can throw this in:

<script2 src="/path/to/jquery.min.js"></script2>

Boom!

And don't worry, script2 won't re-download scripts if they're already loaded.

Promise-based imperative loading too!

Imperatively load scripts with VueScript2.load:

VueScript2.load('/path/to/jquery.min.js').then(function () {
  $('#msg').text('Hello from VueScript2!')
})

For 99% of use-cases this is totally sufficient and you do not need the overhead of RequireJS or SystemJS or whatever else. That's especially true given that Vue.js is normally used with Browserify or Webpack, which handle complicated dependency management for you.

NOTE: scripts injected using VueScript2.load are always async.

Delayed execution of inlined JavaScript

Want to run some JavaScript only when a specific "page"/route is visited and only after a library has finished loading? Simple!

<script2 src="/path/to/jquery.min.js"></script2>
<script2>
// Ordered execution should ensure that '$' is available here
$(document).ready(function () {
  // this code runs *only* when the route
  // that contains this code is loaded! :D->-<
})
</script2>
Cleanup unused resources with the unload attribute

The unload attribute accepts JS expressions to run when the component is destroyed. This prevents your SPA from accumulating stuff in memory that's not being used:

<script2 src="/path/to/jquery.min.js" unload="jQuery.noConflict(true)"></script2>
Special support for async attribute

Although technically all scripts are inserted with s.async = false (since we're using document.write, see this wonderful article by Jake Archibald for details), setting the async attribute does make a meaningful difference.

By default, the loading of <script2> tags is serialized using promises so that one script loads after another has finished. If you don't care about the loading order, add async to have the script injected into the page immediately.

You can mix and match so that some <script2> tags are loaded immediately while others wait for the ones before them:

<script2 src="jquery.min.js"></script2>
<script2>$('#foo').text('hi!')</script2>
<!-- Load next script immediately, don't wait for jQuery -->
<script2 src="lib.js" async></script2>

Writing <script> instead of <script2> using script2ify

The script2ify browserify transform below will (fairly safely) dynamically replace <script> tags with <script2> tags within .ejs, .html, and even .vue files!

var through = require('through2')
// This will replace <script> with <script2> in .html, .vue and .ejs files
// EXCEPT:
// - within <!-- comments -->
// - top-level <script> tags within .vue files
// Additional exclusion per: http://www.rexegg.com/regex-best-trick.html
// Excluding <pre> tags did not seem to work, however.
function script2ify (file) {
  return !/\.(vue|html|ejs)$/.test(file) // edit to support other file types
  ? through()
  : through(function (buf, encoding, cb) {
    // avoid replacing top-level <script> tags in .vue files
    var regex = /\.vue$/.test(file)
    ? /<!--.*?-->|^<script>|^<\/script>|(?:<(\/)?script([ >]))/gm
    : /<!--.*?-->|(?:<(\/)?script([ >]))/gm
    var replacement = (m, p1, p2) => p2 ? `<${p1 || ''}script2${p2}` : m
    cb(null, buf.toString('utf8').replace(regex, replacement))
  })
}

History

See CHANGELOG.md

License

MIT

vue-script2's People

Contributors

akhoury avatar bichikim avatar grempe avatar mingchuno avatar taoeffect avatar vgavro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vue-script2's Issues

strategy for waiting until multiple scripts have loaded

I'm loading multiple scripts and I want to defer my init function until all the scripts have finished loading

  mounted() {
    VueScript2.load('//unpkg.com/three').then(() => {
      setTimeout(() => {
        this.init();
      }, 1000);
    });
    VueScript2.load('//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5.1/dat.gui.min.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/shaders/CopyShader.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/postprocessing/EffectComposer.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/postprocessing/RenderPass.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/postprocessing/ShaderPass.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/shaders/HorizontalBlurShader.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/shaders/VerticalBlurShader.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/shaders/FilmShader.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/shaders/LuminosityHighPassShader.js');
    VueScript2.load('//unpkg.com/[email protected]/examples/js/postprocessing/UnrealBloomPass.js');
    VueScript2.load('//cdn.rawgit.com/felixturner/bad-tv-shader/master/BadTVShader.js');
  },

As you see right now I'm just using a lame hack with a 1000ms timeout

Is there a way to use some kind of promise that will only return true once all 10 of these scripts have completed loading?

CSS loading

per https://github.com/muicss/loadjs/issues/23

scripts with document.write to fails to execute

scripts with document.write fails to execute. is there any workaround to bypass this ? it is working without vue.. it doesnt work when i use the script2.

this is the warning :
Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

Subresource Integrity (SRI) 'crossorigin' prop not being written into script tag. Breaks SRI

I am trying the following tag:

<script2 src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js" integrity="sha384-hfPZ3T7eceGKgB/awoakGSSccX6jYRvOfO3uJYt0+HT1VX1IuRg/4NeOax+WHaQH" crossorigin="anonymous"></script2>

However, in the final DOM output, the crossorigin prop is not being emitted. Copying from the Vue Dev tool on Chrome the following attributes are shown for the script2 tag I see all relevant props (src, integrity, crossorigin) are being set properly:

async: undefined prop
crossorigin: "anonymous"
integrity: "sha384-hfPZ3T7eceGKgB/awoakGSSccX6jYRvOfO3uJYt0+HT1VX1IuRg/4NeOax+WHaQH"
src: "https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js"
text: undefined
type: undefined
unload: undefined

But the DOM outputs:

<script src="https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js" integrity="sha384-hfPZ3T7eceGKgB/awoakGSSccX6jYRvOfO3uJYt0+HT1VX1IuRg/4NeOax+WHaQH" type="text/javascript"></script>

As you can see, the crossorigin is being dropped and this prevents most uses of SRI from working since in most cases a CORS preflight has to be done (e.g. when loading script from a CDN). The following error is thrown in Chrome when trying to load the page with this script tag:

Subresource Integrity: The resource 'https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js' has an integrity attribute, but the resource requires the request to be CORS enabled to check the integrity, and it is not. The resource has been blocked because the integrity cannot be enforced.
vue-script2.js?4ec5:84

Uncaught (in promise) Error: https://cdnjs.cloudflare.com/ajax/libs/zxcvbn/4.3.0/zxcvbn.js(…)
s.onerror   @   vue-script2.js?4ec5:84

For testing you can generate valid SRI hash easily using this tool:

https://www.srihash.org/

And you can learn more about SRI here:

https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity

Crash at IE

As we can see on the message error, the js construction isnt right:

Image of Error

Image of message

And it crashes the website.

install,run error

main.js
import Vue from 'vue'
import Demo from './Demo'

Vue.config.productionTip = false

var x = require('vue-script2')
console.log(x)
Vue.use(x)

/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(Demo)
})


error

浏览器控制台(chrome console)

vipClub.vue?9a8b:164 Uncaught ReferenceError: VueScript2 is not defined
at Object.eval (vipClub.vue?9a8b:164)
at eval (1018:319)
at Object. (app.js:7155)
at webpack_require (app.js:706)
at fn (app.js:112)
at eval (vipClub.vue?effb:1)
at Object. (app.js:6989)
at webpack_require (app.js:706)
at fn (app.js:112)
at eval (lvshou.js?a593:1)
(anonymous) @ vipClub.vue?9a8b:164
.....

How do it for me?

Vue 2.x support

Just released! Forgot to create a pull request for this, just pushed to master since it's a small project.

Using with simultaneously rendered components

I have a view in my app which renders multiple video player components in a v-for loop. This component uses vue-script2's promise based loading to load a remote script in the mounted() lifecycle hook.

As these components are rendered simultaneously, I notice the remote script is actually added multiple times (once for each component). I'm assuming this package doesn't perform any checks for pending scripts or anything like that? Should I be using a different method for loading these?

Transpile doesn't work

I am trying to transpile vue-script2 inside of a Nuxt application in order to support IE11. I am using vue-google-adsense and vue-script2 is a dependency. However, even in Chrome I'm receiving this error when transpiling: "Unknown custom element: ".

Any suggestions on how I can make vue-script2 compatible with IE11?

IE 11 Expected ':'

When using this in my app, it seems to get stuck on IE 11 with the message Expected ':' with a link to the code that points here

// keys are the scripts that is loading or loaded, values are promises
install(Vue) { <--- Here
    if (Script2.installed) return;

My code works on other browsers I have tested, (chrome, firefox). But this halts my code in IE11. Any ideas on this?

Expected ':' issue in IE v2.1.0

Hi,

I'm experiencing an Expected ':' error on IE11 that is happening on vue-script2 plugin import.

Works correctly when downgraded to the previous version (2.0.3).
Can you take a look at what's not correct there with the newest version?

Thanks,
Emīls

Emit "load" and "error" events on loading

For usage like this:

<template>
<script2 src="myscript.js" @load="loaded" />
<template>
<script>
export default {
   methods: {
       loaded () {
          window.myscriptModule.youVeGotTheIdea()
       }
   }
}
</script>

fixes with #29

Could not find a declaration file for module

[ts]
Could not find a declaration file for module 'vue-script2'. '~/node_modules/vue-script2/dist/vue-script2.js' implicitly has an 'any' type.
Try npm install @types/vue-script2 if it exists or add a new declaration (.d.ts) file containing declare module 'vue-script2';

work without using vue-router? where to put script2? MIME type error

Hi,

some quick questions:

  1. Is it possible to use vue-script2 without vue-router?

  2. Where do we put the tags in the .vue element that we are trying to load extra script tags onto (like jquery for example) ? in the tag? in the <script>tag ? outside both of those above the <style> tag?

  3. I'm currently getting an error: Refused to execute script from 'http://127.0.0.1:4000/asesets/js/lib/imagesloaded.min.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.
    Any ideas on why? the script2 tag is being loaded with type="text/javascript"? i'm wondering if this could an issue with my environments buildpack but not sure....

VS2 isn't able to load scripts on client side render

Hi

I have tried to implement VS2 in my setup and i'm having issues with making it work as hoped.

My setup is a SPA with SSR abilities (based on VueHackernews demo). First time the script is running and the desired service is loaded, then navigating away and back will cause the service to do nothing.

I have tried the <script2 unload src="...." way and the

VueScript2.load('service.js').then(() => { console.log('loaded') });

Same result both times.

This is the service I'm testing with:
<div data-widget-url="https://septima.dk/widget/config/layer.json"></div>
<script src="https://widgetconfig.septima.dk/widgetconfig.js"></script>

Is there a way to force redownload or rerender/-load in vuescript2?

Safari 9 cross-origin

I know that there was a recent fix to the cross-origin issue, and I have checked that my package is up to date.
Everything works great except on safari 9 it doesn't work, and I get the following error:

[Error] Cross-origin script load denied by Cross-Origin Resource Sharing policy.
(anonymous function) (vue-script2.js:102)
Promise ([native code], line 0)
load (vue-script2.js:73)
a (vue-script2.js:49)
PromiseResolutionHandlerFunction ([native code], line 0)

I've tried loading inside script2 tag with and without crossorigin="anonymous"

      <script2 src="//s7.addthis.com/js/300/addthis_widget.js" crossorigin="anonymous" type="text/javascript"></script2>
      <script2>
        console.log('vue2script')
        addthis.button('.addthis_btn')
      </script2>

In safari the rendered html looks like this:

<script src="//s7.addthis.com/js/300/addthis_widget.js" type="text/javascript" crossorigin="anonymous"></script>``

Is safari 9 not supported? any insight would be very helpful!
thanks

help about js file 404

which I want to do is throw an old html page into this vue project.

<!--example3.html file-->
<div style="color: red;">
    I am a html file container script
    <script2 src="../1.js"></script2>
</div>
<!--1.js file-->
var App = function () {
    console.log('1.js run')
}

App();

project structure
image

thanks for your help!

version: '2.1.0', IE11

version: '2.1.0', broke the IE11

798b050

dist/vue-script2.js

15 -  version: '2.0.3', // grunt will overwrite to match package.json
16 -  loaded: {}, // keys are the scripts that have been loaded
17 -  install: function install(Vue) {
15 +  version: '2.1.0',
16 +  // grunt will overwrite to match package.json
17 +  loaded: {},

19 +  // keys are the scripts that is loading or loaded, values are promises
20 +    install(Vue) { 

IE error:
SCRIPT1003: Предполагается наличие ':'

in bundle:

/*!
  * vue-script2 v2.1.0
  * (c) 2016-2019 Greg Slepak
  * @license MIT License
  */
t.exports=function(){"use strict";var t={installed:!1,p:Promise.resolve(),version:"2.1.0",loaded:{},install(n){if(!t.installed)

Thank you so much for creating this!

Hello @taoeffect !
I just wanted to express my gratitude for this library.
This has been incredibly useful, not just because it supports the obvious case where one wants to load vendor scripts on demand, but also because there are cases where one is using legacy code which cannot be used via webpack easily (an example being a file of type "text/paperscript", a paper.js hack).
Additionally, the ordered loading has been really helpful to me since I have some dependency order in my legacy scripts, to get around which I'd probably need a PhD in webpack.
I believe this is a really well thought out library, at least from a developer ergonomics perspective and it ties closely with Vue's developer friendly approach.

Feel free to close this if you want, as this is really a non issue. :-)

Bug with entities

Hi, I'm using script2 directly in html files, but having a problem with entities where for example if (1 > 0) becomes if (1 & gt; 0) which of course breaks javascript.

Is there a fix for this?

document.referrer when loaded

I'm loading a 3rd party script it checks document.referrer when it runs. It seems they are unable to get the proper referrer. Should they be able to get that properly from a VueScript2.load() call? I wait until the promise resolves before calling their setup function.

Vue-Script2 for Ld+Json

I use this for produce LD+JSON string like this:

<script2
      type="application/ld+json"
      v-text="jsonLdProduct">
</script2>

but printed as

<script type="text/javascript">
         {string: "string"}
</script>

Is there any way to set script type ?

Passing Data to Vue Instance

Is there any way to pass data to the Vue instance from a function inside a script2 tag? I have a function inside a script2 tag which I want to react to in my Vue component and can't seem to access anything from inside the script2 tag.

Support for v-html

Hi, I am was hoping this library would help with v-html injected script2 tags, but it appears there isn't support for that yet.

Using cash in vue-script2

I write in html code
<img src="main.js" style=display:none;>
and

mounted() {
  Script2.load('main.js').then(function () {
     console.log( "Loaded !" );
    })
}

I test this in chrome dev tools and not see that script loaded from cash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.