Git Product home page Git Product logo

little-loader's Introduction


NOTICE:

This repository has been archived and is not supported.

No Maintenance Intended


NOTICE: SUPPORT FOR THIS PROJECT HAS ENDED

This projected was owned and maintained by Walmart. This project has reached its end of life and Walmart no longer supports this project.

We will no longer be monitoring the issues for this project or reviewing pull requests. You are free to continue using this project under the license terms or forks of this project at your own risk. This project is no longer subject to Walmart's bug bounty program or other security monitoring.

Actions you can take

We recommend you take the following action:

  • Review any configuration files used for build automation and make appropriate updates to remove or replace this project
  • Notify other members of your team and/or organization of this change
  • Notify your security team to help you evaluate alternative options

Forking and transition of ownership

For security reasons, Walmart does not transfer the ownership of our primary repos on Github or other platforms to other individuals/organizations. Further, we do not transfer ownership of packages for public package management systems.

If you would like to fork this package and continue development, you should choose a new name for the project and create your own packages, build automation, etc.

Please review the licensing terms of this project, which continue to be in effect even after decommission.

Little Loader

A lightweight, IE8+ JavaScript loader that is actually tested...

Travis Status Coverage Status size size (gz)

Sauce Test Status

... with a very narrow set of objectives:

  • Tested all the way down to IE8
  • Reliably calls back after script loads
  • Captures script load errors down to IE8
  • Really, really small (clocking in at ~519 minified + gzipped bytes)
  • ... and that's it!

We currently test:

  • Karma - Travis: PhantomJS, Firefox
  • Selenium - Travis: PhantomJS, Firefox
  • Selenium - Sauce Labs:
    • Windows: Firefox, Chrome, IE8-11
    • Mac: Safari

Usage

Integration

Alone, little loader attaches to window._lload for loading your Javascript:

<script>
  window._lload("http://example.com/foo.js", function (err) {
    // `err` is script load error.
    // otherwise, foo.js is loaded!
  }/*, [optional context (`this`) variable here] */);
</script>

If you use an AMD bundling tool (like RequireJS):

define(["little-loader"], function (load) {
  load("http://example.com/foo.js", function (err) {
    // ... your code ...
  });
});

If you use a CommonJS bundling tool (like Webpack):

var load = require("little-loader");

load("http://example.com/foo.js", function (err) {
  // ... your code ...
});

Calling

Little loader can be called in a number of ways:

// Load a script and don't worry about a callback
load("http://foo.com/foo.js");

// Load, then callback (and optionally with context.)
load("http://foo.com/foo.js", callback);
load("http://foo.com/foo.js", callback, this);

// Load, call `setup(script)` on the script tag before insertion, no callback
load("http://foo.com/foo.js", {
  setup: setup,         // setup(script)
  context: this         // (optional)
});

// Load, call `setup(script)` on the script tag before insertion, then
// callback with context (two ways)
load("http://foo.com/foo.js", {
  setup: setup,         // setup(script)
  callback: callback,   // callback(err)
  context: this
});
load("http://foo.com/foo.js", {
  setup: setup,         // setup(script)
  callback: callback    // callback(err)
}, this);

Installation

CDN

For the ready-to-use version from CDN, use

<!-- Minified, production version -->
<script src="https://unpkg.com/little-loader@VERSION/dist/little-loader.min.js"></script>
<!-- Development version -->
<script src="https://unpkg.com/little-loader@VERSION/lib/little-loader.js"></script>

NPM

To include little-loader as part of your own build, first install from npm:

$ npm install --save little-loader

The library has a UMD wrapper and should work like any other AMD or CommonJS module with your favorite bundling tool (Webpack, RequireJS, etc.).

If you do not use a CommonJS or AMD loader tool, then little loader will be exposed as the window._lload variable.

Development

Development requires two installation steps:

$ npm install
$ npm run install-dev

After that, run the full lint + tests:

$ npm run check

You can try out the live functional tests fixtures with our static server:

$ npm run server

and navigate to: http://127.0.0.1:3001/test/func/fixtures/

Tests

We run both Karma (client-side) and Selenium (functional) tests.

The Karma tests are faster and more flexible, but slightly "off" from real-world use because of their execution environment. We use Karma tests to kick the tires on our AMD and CommonJS abstractions and little, one-off use case scenarios.

The Selenium tests are slower and klunky, but they are the "real deal" executing little-loader in exactly the same manner as would be used on a real web page. We use Selenium to test a core set of fundamental use cases across all browsers in our matrix.

Parallel Local Tests

Our CI is setup with a specific optimized parallel workflow. To run parallel functional tests in development, here are some helper tasks...

Local Browsers

$ TEST_PARALLEL=true \
  builder envs test-func-local \
  --setup=setup-local \
  --buffer \
  '[ { "TEST_FUNC_PORT": 3030, "ROWDY_SETTINGS":"local.phantomjs" },
     { "TEST_FUNC_PORT": 3040, "ROWDY_SETTINGS":"local.firefox" },
     { "TEST_FUNC_PORT": 3050, "ROWDY_SETTINGS":"local.chrome" }
   ]'

The TEST_PARALLEL flag indicates to not do in-test setup which would conflict with other test processes. We also rely on setting TEST_FUNC_PORT specifically to non-conflicting ports with at least 3 ports total from the starting number for the two separate static servers we run during tests.

Sauce Labs

To run Sauce Labs tests in parallel from a local machine, you'll need the sc binary, which can be force installed with:

$ SAUCE_CONNECT_DOWNLOAD_ON_INSTALL=true npm install sauce-connect-launcher

After this, the module is available at: node_modules/sauce-connect-launcher/sc/*/bin/sc

From there, you can invoke our helper local commands:

$ TEST_PARALLEL=true \
  SAUCE_USERNAME=<INSERT_USERNAME> \
  SAUCE_ACCESS_KEY=<INSERT_ACCESS_KEY> \
  builder envs test-func-sauce \
  --setup=setup-sauce \
  --buffer \
  '[ { "TEST_FUNC_PORT": 3030, "ROWDY_SETTINGS":"sauceLabs.IE_8_Windows_2008_Desktop" },
     { "TEST_FUNC_PORT": 3040, "ROWDY_SETTINGS":"sauceLabs.IE_9_Windows_2008_Desktop" },
     { "TEST_FUNC_PORT": 3050, "ROWDY_SETTINGS":"sauceLabs.IE_10_Windows_2012_Desktop" }
   ]'

Releases

IMPORTANT - NPM: To correctly run preversion your first step is to make sure that you have a very modern npm binary:

$ npm install -g npm

First, you can optionally edit and commit the project history.

$ vim HISTORY.md
$ git add HISTORY.md
$ git commit -m "Update history for VERSION"

Now we're ready to publish. Choose a semantic update for the new version. If you're unsure, read about semantic versioning at http://semver.org/

$ npm version VERSION|major|minor|patch -m "Version %s - INSERT_REASONS"

Now postversion will push to git and publish to NPM.

little-loader's People

Contributors

cwstege avatar exogen avatar mmonto7 avatar npmcdn-to-unpkg-bot avatar ryan-roemer 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  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

little-loader's Issues

Feature: Add `script.onerror` handler.

  • Add onerror handler
  • Test errors down to IE8 (may be future work).
  • Figure out IE8 script.onerror story.
  • Update doc byte sizes.
  • Update doc usage stuff.

New API:

window._lload("http://example.com/foo.js", function (err) {
  if (err) { console.log("OH NOES", err); }
  // foo.js is loaded!
}/*, [optional context variable here] */);

/cc @PeoB

Cannot read property 'parentNode' of undefined

When I try to test my loading function using Jest, I get this error.

TypeError: Cannot read property 'parentNode' of undefined

      at _addScript (node_modules/little-loader/lib/little-loader.js:43:17)
      at _lload (node_modules/little-loader/lib/little-loader.js:209:7)

I found this error in an old issue too #37 .

What is your recommandation to test your lib using a test runner like Jest ?
Thank you

Sync or Async?

Just to be clear, if I use this:

// Load a script and don't worry about a callback
load("http://foo.com/foo.js");

is this going to run synchronously?

Documentation: Useful patterns around little-loader

  • DOCUMENT: A retry pattern and do it in tests.
  • DOCUMENT: A timeout pattern (and note script could still fire after).
  • DOCUMENT: Load array of scripts in series then fire callback
  • DOCUMENT: Load array of scripts in parallel then fire callback

Feature: Minified distribution

  • Choose uglify or closure compiler based on what's best.
  • Dump out to dist/little-loader.min.js on preversion, outside of source.
  • Add versioning instructions
  • Add instructions for bower / CDN users for npmcdn.

TEST: `safari_7_OS_X_10_9_Desktop` on Sauce fails a lot.

Here's a Sauce session failing: https://saucelabs.com/tests/e5e124818cf248c4b65b265762368909

From cached debug notes from Sauce:

New session request was cancelled before a Sauce Labs virtual machine was found

This means that your test runner decided to end the job before it had fully initialized on Sauce's end. There are a few potential causes:

You're running too many tests at a time: Check the left sidebar on your Account page (https://saucelabs.com/account). It shows a "Parallel tests" number, which is the maximum number of tests you can run at a time, based on your subscription level. If your account can run 2 parallel tests, and you're launching 10, 8 will be "queued" until one of your tests finishes and a slot frees up. However, if this takes a long time, your test runner may choose to end the queued jobs after a few minutes instead of waiting. Just make sure you're launching a reasonable number of simultaneous tests for your account.
High job wait times: Check our status page (http://status.saucelabs.com/) and/or follow @sauceops on Twitter for up-to-the-minute news about any issues within the service. If something causes demand for certain VMs to stack up, your jobs may be queued and (as above) terminated by your test runner.
Tests that end this way are never taken out of your minutes.

Here's a sample local failure:

$ time \
>   ROWDY_OPTIONS='{ "client": { "logger":true } }' \
>   ROWDY_SETTINGS="sauceLabs.safari_7_OS_X_10_9_Desktop" \
>   SAUCE_USERNAME=wml-little-loader \
>   SAUCE_ACCESS_KEY=SNIPPED \
>   SAUCE_TUNNEL_ID=dev-wml-little-loader \
>   SAUCE_CONNECT_VERSION=4.3.10 \
>   npm run test-func-raw

> [email protected] test-func-raw /Users/rye/scm/wm/little-loader
> mocha --opts test/func/mocha.opts test/func/spec/



[CLIENT] [cmd] POST /wd/hub/session {"desiredCapabilities":{"browserName":"safari","version":"7","javascriptEnabled":true,"locationContextEnabled":true,"handlesAlerts":true,"rotatable":true,"platform":"OS X 10.9","loggingPrefs":{"browser":"ALL","driver":"ALL"},"name":"wml-little-loader","tags":["wml-little-loader@local"],"public":"public","build":"local","requestOrigins":{"url":"http://webdriver.io","version":"3.2.6","name":"webdriverio"}}}
[CLIENT] [init] a91fc249975a4205a3a9a6a80d666c51
[CLIENT] [result] POST /wd/hub/session {"status":0,"sessionId":"a91fc249975a4205a3a9a6a80d666c51","value":{"takesScreenshot":true,"version":"7.1.7","cssSelectorsEnabled":true,"javascriptEnabled":true,"secureSsl":true,"platform":"MAC","browserName":"safari","webdriver.remote.sessionid":"a91fc249975a4205a3a9a6a80d666c51","hasMetadata":true},"state":null,"hCode":99137470,"class":"org.openqa.selenium.remote.Response"}
[CLIENT] [cmd] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/timeouts {"type":"implicit","ms":200}
[CLIENT] [result] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/timeouts {"status":0,"orgStatusMessage":"The command executed successfully."}
  advanced
[CLIENT] [cmd] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/url {"url":"http://127.0.0.1:3030/test/func/fixtures/advanced.html"}
[CLIENT] [result] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/url {"status":0,"orgStatusMessage":"The command executed successfully."}
[CLIENT] [cmd] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/elements {"using":"css selector","value":".e2e-error"}
[CLIENT] [result] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/elements {"status":0,"sessionId":"a91fc249975a4205a3a9a6a80d666c51","value":[],"state":null,"hCode":1510480563,"class":"org.openqa.selenium.remote.Response"}
NoSuchElement: An element could not be located on the page using the given search parameters. 
    at elements(".e2e-error") - getText.js:42:17
    at getText(".e2e-after-load-fourth") - advanced.spec.js:39:8 
    1) loads advanced scenario

  basic
[CLIENT] [cmd] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/url {"url":"http://127.0.0.1:3030/test/func/fixtures/basic.html"}
[CLIENT] [result] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/url {"status":0,"orgStatusMessage":"The command executed successfully."}
[CLIENT] [cmd] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/elements {"using":"css selector","value":".e2e-error"}
[CLIENT] [result] POST /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51/elements {"status":0,"sessionId":"a91fc249975a4205a3a9a6a80d666c51","value":[],"state":null,"hCode":981620018,"class":"org.openqa.selenium.remote.Response"}
NoSuchElement: An element could not be located on the page using the given search parameters. 
    at elements(".e2e-error") - getText.js:42:17
    at getText(".e2e-after-load") - basic.spec.js:21:8 
    2) loads basic script

[CLIENT] [cmd] DELETE /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51 {}
[CLIENT] [result] DELETE /wd/hub/session/a91fc249975a4205a3a9a6a80d666c51 {"status":0,"sessionId":"a91fc249975a4205a3a9a6a80d666c51","value":""}

  0 passing (22s)
  2 failing

  1) advanced loads advanced scenario:
     NoSuchElement: An element could not be located on the page using the given search parameters.
      at getText(".e2e-after-load-fourth") - advanced.spec.js:39:8

  2) basic loads basic script:
     NoSuchElement: An element could not be located on the page using the given search parameters.
      at getText(".e2e-after-load") - basic.spec.js:21:8




npm ERR! Darwin 14.5.0
npm ERR! argv "node" "/Users/rye/.nvm/v0.10.40/bin/npm" "run" "test-func-raw"
npm ERR! node v0.10.40
npm ERR! npm  v2.14.12
npm ERR! code ELIFECYCLE
npm ERR! [email protected] test-func-raw: `mocha --opts test/func/mocha.opts test/func/spec/`
npm ERR! Exit status 2
npm ERR! 
npm ERR! Failed at the [email protected] test-func-raw script 'mocha --opts test/func/mocha.opts test/func/spec/'.
npm ERR! This is most likely a problem with the little-loader package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     mocha --opts test/func/mocha.opts test/func/spec/
npm ERR! You can get their info via:
npm ERR!     npm owner ls little-loader
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/rye/scm/wm/little-loader/npm-debug.log

real  0m23.594s
user  0m1.295s
sys 0m0.219s

Support crossorigin="anonymous"

Scripts loaded using little-loader can't be debugged using window.onerror because of CORS (you just get the standard 'Script error.' error). It would be nice to be able to set the crossorigin policy on the <script /> tag so that we can debug scripts that are hosted on a third party domain (such as a CDN)

TEST SCENARIO: CDN / offline stuff.

Tasks

  • Test CDN resouces: jQuery, Underscore
    • HTTP URL
    • HTTPS URL
    • Protocol-independent URL
    • Have test/func/spec/online.spec.js scenario that can be disabled for offline tests.

Done

  • Test other port-served scripts.
  • Test "previous version" of little loader from CDN ( On second thought, let's not do this )

/cc @exogen

Optimize source for mingzipped size.

I was contemplating refactoring little-loader a bit to try to make it even smaller (I kinda like that kind of challenge, no golf, promised), then I realized that what I was aiming for (smallest mingzipped size) may not be what you're aiming for...

So, if conflict arises, what do you prefer? A smaller minified build or a smaller mingzipped build?

Support loading multiple JavaScript files before calling back

I'm considering using little-loader to dynamically load in component suites at run-time. Currently, there is only support for a singular src string. I would welcome support for an array of src strings, to load in multiple libraries. Is this in alignment with the roadmap?

_addScript throws if there is no other script in the <head>

On a page with no script tags in the <head> (only in <body>) the loader appears to throw exceptions in _addScript (for any script load requested).

The call stack looks like:

little-loader.js:43 Uncaught TypeError: Cannot read property 'parentNode' of undefined

_addScript  @   little-loader.js:43
_lload  @   little-loader.js:209
// my code below that

The cause seems to be the assumption of the existence of at least one script tag in <head> here:

var firstScript = document.getElementsByTagName("script")[0];

// Append the script to the DOM, triggering execution.
firstScript.parentNode.insertBefore(script, firstScript);

Feature: UMD Wrapper + Tests

Tasks

  • Add UMD wrapper
  • Likely want to keep window._lload in all scenarios for joint "inline + built" bootstrap scenario.
  • TEST: webpack-built frontend
  • TEST: RequireJS frontend

What about CSS?

Some librairies (I'm thinking of CodeMirror here, but others apply too, I'm sure) come with large style sheets that are better loaded asynchronously too, and it is always nice to wait for the CSS to load as well as the lib itself.

I'm ignorant about the topic, but something tells me that there must be various pitfalls in that regard too...

Is it beyond the scope of little_loader?

This may end up being a slippery slope though (why not handle images, etc...), and I'd understand if you wanted to keep your lib lean and focused.

Latest Sauce response gives no browser status

Currently our browser badge is just showing "unknown":

...because the official Sauce badge itself is showing the same:

Possibly due to the latest Sauce results not reflecting the last Travis build of master? This could potentially be fixed by switching the badge to URL http://badges.herokuapp.com/travis/walmartlabs/little-loader/sauce/wml-little-loader, which specifically attempts to correlate the master Travis build with particular Sauce jobs instead of just using the latest (potentially non-master) Sauce build, but that's not working either (I think because it expects to correlate the build name/number in a certain way).

Badges: browsers, file size, others?

My project for generating prettier Sauce Labs badges is up at exogen/badge-matrix. It's currently running on a Heroku dyno that doesn't need to sleep, at badges.herokuapp.com. Here's a badge for little-loader:

little-loader Browser Support

Should be easy to host anywhere if you don't like Heroku. (For reference, on my connection Sauce Labs' badge has avg response time of 0.41s and the image is 28K; badge-matrix on my hobby Heroku dyno has avg response time of 0.6s and the image is 2.4K, not too terrible. The time is dwarfed by potentially needing to talk to the APIs anyway, no matter where hosted.)

I also happened across ngryman/badge-size which can generate a file size badge for any file in your repo. I think that's cool because it's something we're emphasizing, and we currently need to update it in the README every time it changes.

We don't have any dist files in our repo to point it at yet, but here's a size badge for the source file (it can tell you the gzip size too):

little-loader size

The test suite fails on OS X 10.10

The fs-events package refuses to install, and the test runner (npm run check) crashes with

[SERVER] [error] Error: Missing /Users/pygy/src/little-loader/node_modules/selenium-standalone/.selenium/chromedriver/2.18-x64-chromedriver
  1) "before all" hook

Here's the full log, including early successes then a crash.

This is on the master branch, freshly cloned.

~/s/little-loader git:master ❯❯❯ node -v
v5.1.1
~/s/little-loader git:master ❯❯❯ npm -v
3.5.2

Code Coverage

  • Extract code coverage from client-side to backend selenium tests
  • Hook up to coveralls
  • Hook up badge o' awesome.

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.