├── .babelrc
├── .eslintrc
├── .gitignore
├── README.md
├── example
├── index.html
├── index.js
└── script.js
├── lib
└── index.js
├── package.json
├── server.js
├── src
└── index.js
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "stage": 0
3 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "rules" :{
4 | "quotes": [1, "single"],
5 | "no-unused-vars": [1, {"vars": "all", "args": "all"}],
6 | "strict": [2, "never"]
7 | },
8 | "env":{
9 | "browser": true,
10 | "node" : true
11 | }
12 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # osx noise
2 | .DS_Store
3 | profile
4 |
5 | # xcode noise
6 | build/*
7 | *.mode1
8 | *.mode1v3
9 | *.mode2v3
10 | *.perspective
11 | *.perspectivev3
12 | *.pbxuser
13 | *.xcworkspace
14 | xcuserdata
15 |
16 | # svn & cvs
17 | .svn
18 | CVS
19 | node_modules
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | react-loadscript
2 | ---
3 |
4 | `npm install react react-loadscript --save`
5 |
6 | script-loading as a component
7 |
8 | (I'm so sorry)
9 |
10 | ```js
11 | import {Script} from 'react-loadscript';
12 |
13 | class App {
14 | render(){
15 | return
20 | }
21 | }
22 | ```
23 |
24 | uses promises + a simple cache to prevent duplicate script loads. enjoy!
25 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/example/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {Script} from '../src';
3 |
4 | class App {
5 | render(){
6 | return
9 | }
10 | }
11 |
12 | React.render(, document.getElementById('root'));
--------------------------------------------------------------------------------
/example/script.js:
--------------------------------------------------------------------------------
1 | console.log(123);
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, '__esModule', {
4 | value: true
5 | });
6 |
7 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
8 |
9 | var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } };
10 |
11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
12 |
13 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
14 |
15 | function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
16 |
17 | var _react = require('react');
18 |
19 | var _react2 = _interopRequireDefault(_react);
20 |
21 | var promises = {};
22 |
23 | function loadScript(src) {
24 | if (promises[src]) {
25 | return promises[src];
26 | }
27 | var promise = promises[src] = new Promise(function (resolve) {
28 | var el = document.createElement('script');
29 | var loaded = false;
30 | el.onload = el.onreadystatechange = function () {
31 | if (el.readyState && el.readyState !== 'complete' && el.readyState !== 'loaded' || loaded) {
32 | return false;
33 | }
34 | el.onload = el.onreadystatechange = null;
35 | loaded = true;
36 | resolve();
37 | };
38 |
39 | el.async = true;
40 | el.src = src;
41 | var head = document.getElementsByTagName('head')[0];
42 | head.insertBefore(el, head.firstChild);
43 | });
44 |
45 | return promise;
46 | }
47 |
48 | var Script = (function (_React$Component) {
49 | _inherits(Script, _React$Component);
50 |
51 | function Script() {
52 | _classCallCheck(this, Script);
53 |
54 | _get(Object.getPrototypeOf(Script.prototype), 'constructor', this).apply(this, arguments);
55 |
56 | this.state = {
57 | done: false
58 | };
59 | }
60 |
61 | _createClass(Script, [{
62 | key: 'componentWillMount',
63 | value: function componentWillMount() {
64 | var _this = this;
65 |
66 | loadScript(this.props.src).then(function () {
67 | _this.setState({
68 | done: true
69 | });
70 | _this.props.onLoad();
71 | });
72 | }
73 | }, {
74 | key: 'render',
75 | value: function render() {
76 | return this.props.children(this.state);
77 | }
78 | }], [{
79 | key: 'defaultProps',
80 | value: {
81 | src: 'javascript:void(0)',
82 | onLoad: function onLoad() {}
83 | },
84 | enumerable: true
85 | }, {
86 | key: 'propTypes',
87 | value: {
88 | children: _react2['default'].PropTypes.func,
89 | src: _react2['default'].PropTypes.string,
90 | onLoad: _react2['default'].PropTypes.func
91 | },
92 | enumerable: true
93 | }]);
94 |
95 | return Script;
96 | })(_react2['default'].Component);
97 |
98 | exports.Script = Script;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-loadscript",
3 | "version": "1.0.2",
4 | "description": "script tag as a react component",
5 | "main": "./lib/index.js",
6 | "scripts": {
7 | "start": "babel-node server.js",
8 | "build": "babel src -d lib",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/threepointone/react-script.git"
14 | },
15 | "author": "Sunil Pai ",
16 | "license": "ISC",
17 | "bugs": {
18 | "url": "https://github.com/threepointone/react-script/issues"
19 | },
20 | "homepage": "https://github.com/threepointone/react-script#readme",
21 | "devDependencies": {
22 | "babel": "^5.8.21",
23 | "babel-core": "^5.8.22",
24 | "babel-eslint": "^4.0.5",
25 | "babel-loader": "^5.3.2",
26 | "react": "^0.13.3",
27 | "webpack": "^1.11.0",
28 | "webpack-dev-server": "^1.10.1"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 | import WebpackDevServer from 'webpack-dev-server';
3 | import config from './webpack.config';
4 |
5 | const isHot = !!process.env.HOT;
6 |
7 | new WebpackDevServer(webpack(config), {
8 | publicPath: config.output.publicPath,
9 | hot: isHot,
10 | historyApiFallback: true
11 | }).listen(3000, 'localhost', err => console.log(err || 'webpack at localhost:3000'));
12 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | const promises = {};
3 |
4 | function loadScript(src){
5 | if(promises[src]){
6 | return promises[src]
7 | }
8 | let promise = promises[src] = new Promise(resolve => {
9 | var el = document.createElement('script');
10 | var loaded = false;
11 | el.onload = el.onreadystatechange = () => {
12 | if ((el.readyState && el.readyState !== 'complete' && el.readyState !== 'loaded') || loaded) {
13 | return false;
14 | }
15 | el.onload = el.onreadystatechange = null;
16 | loaded = true;
17 | resolve();
18 | };
19 |
20 | el.async = true;
21 | el.src = src;
22 | let head = document.getElementsByTagName('head')[0];
23 | head.insertBefore(el, head.firstChild);
24 |
25 | });
26 |
27 | return promise;
28 | }
29 |
30 | export class Script extends React.Component{
31 | static defaultProps = {
32 | src: 'javascript:void(0)',
33 | onLoad: () => {}
34 | }
35 | static propTypes = {
36 | children: React.PropTypes.func,
37 | src: React.PropTypes.string,
38 | onLoad: React.PropTypes.func
39 | }
40 | state = {
41 | done: false
42 | }
43 | componentWillMount() {
44 | loadScript(this.props.src).then(()=> {
45 | this.setState({
46 | done: true
47 | });
48 | this.props.onLoad();
49 | });
50 | }
51 | render(){
52 | return this.props.children(this.state);
53 | }
54 | }
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | import webpack from 'webpack';
2 |
3 | let config = {
4 | devtool: 'source-map',
5 | target: 'web',
6 | entry: {
7 | example: ['./example/index.js']
8 |
9 | },
10 | output: {
11 | path: __dirname,
12 | filename: 'example/bundle.js',
13 | publicPath: '/'
14 | },
15 | module: {
16 | loaders: [{
17 | test: /\.js$/,
18 | exclude: /node_modules/,
19 | loaders: ['babel-loader']
20 | }]
21 | },
22 | resolve: {
23 | extensions: ['', '.js', '.jsx']
24 | },
25 | plugins: []
26 | };
27 |
28 | if(process.env.HOT){
29 | config = {
30 | ...config,
31 | devtool: 'eval-source-map',
32 | entry: Object.keys(config.entry).reduce((o, key) => ({...o, [key]: [
33 | 'webpack-dev-server/client?http://localhost:3000', // WebpackDevServer host and port
34 | 'webpack/hot/only-dev-server'
35 | ].concat(config.entry[key])}), {}),
36 | module: {...config.module,
37 | loaders: [{
38 | ...config.module.loaders[0],
39 | loaders: [
40 | 'react-hot'
41 | ].concat(config.module.loaders[0].loaders)
42 | }]
43 | },
44 | plugins: [
45 | new webpack.HotModuleReplacementPlugin(),
46 | new webpack.NoErrorsPlugin()
47 | ].concat(config.plugins)
48 | };
49 | }
50 |
51 | module.exports = config;
52 |
--------------------------------------------------------------------------------