Skip to content

Instantly share code, notes, and snippets.

@dkarmalita
Last active November 3, 2020 09:04
Show Gist options
  • Save dkarmalita/d4664436765d770b889384e6ca37c248 to your computer and use it in GitHub Desktop.
Save dkarmalita/d4664436765d770b889384e6ca37c248 to your computer and use it in GitHub Desktop.
Babel * in-browser setup with only loader from CDN (only index.html and your app.js neccesary)
/**
* You can use require here
* @example
* const sub = require('./sub')
* console.log('SUB >>',sub.default())
*/
ReactDOM.render((<h1>It Works!</h1>), document.getElementById('root'));
/*
ver: v20201103
url: https://gist.github.com/dkarmalita/d4664436765d770b889384e6ca37c248
cdn: https://gitcdn.xyz/repo/dkarmalita/d4664436765d770b889384e6ca37c248/raw/94ce4b6c7abdd6bf53911437f14850f4d9ad0d04/babel-browser.js
*/
function addHeadScript(url, dataset, cb){
const onFinisg = (err) => { if(typeof cb === 'function') cb(err) }
const script = document.createElement("script");
script.type="text/javascript"
script.onload=(event)=>onFinisg({ event })
script.onerror=()=>onFinisg({ error: new Error(`loading of ${url}`) })
script.src=url
script.async=true
Object.keys(dataset || {}).forEach(dsk => script.dataset[dsk] = dataset[dsk])
document.getElementsByTagName("head")[0].appendChild(script);
}
function addHeadScriptsAsync(urls=[], dataset=null){
return Promise.all(urls.map(url => new Promise((resolve, reject) => {
addHeadScript(url, dataset, (result) => {
if(result.error){ reject(result.error) }
resolve(result.event)
})
})))
}
function babelRegisterPresetPreact(){
Babel.registerPreset("preact", {
plugins: [
[Babel.availablePlugins["transform-react-jsx"], {
"pragma": "h",
"pragmaFrag": "Fragment",
}]
],
});
}
function babelTransform(text) {
var output = Babel.transform(
text,
{
presets: [
Babel.availablePresets["env"],
Babel.availablePresets["stage-3"],
Babel.availablePresets["preact"] || Babel.availablePresets["react"],
],
}
);
return output.code
}
function babelLog(){
console.groupCollapsed(`Babel ${Babel.version}`);
console.log('Avaliable presets:', Babel.availablePresets)
console.log('Avaliable plugins:', Babel.availablePlugins)
console.groupEnd();
}
const scripts = [
'https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.12.1/polyfill.min.js',
'https://unpkg.com/@babel/standalone/babel.min.js',
// 'https://unpkg.com/react@16/umd/react.development.js',
// 'https://unpkg.com/react-dom@16/umd/react-dom.development.js',
]
var dataset = document.currentScript.dataset;
addHeadScriptsAsync(scripts)
.then((events)=>{
babelLog()
if(dataset.preact){ babelRegisterPresetPreact() }
window.babelTransform = babelTransform
return addHeadScriptsAsync(
[
// 'lib/require-polyfill.js',
'https://gitcdn.xyz/repo/dkarmalita/d4664436765d770b889384e6ca37c248/raw/4dd3b6c16778b2ce0b887d73f94e8c874ba76b09/require-polyfill.js'
],
{
projectRoot: './',
main: './index.js',
...dataset,
}
)
})
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hello!</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!--
Load babel & react components and app.js via one babel-browser loader taken from CDN
Look at the gist original for more details:
https://gist.github.com/dkarmalita/d4664436765d770b889384e6ca37c248
-->
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
<script data-project-root="./" data-main="./index.js" src="https://gitcdn.xyz/repo/dkarmalita/d4664436765d770b889384e6ca37c248/raw/94ce4b6c7abdd6bf53911437f14850f4d9ad0d04/babel-browser.js" async></script>
</head>
<body>
<p>Output should appear below.</p>
<hr/>
<div id="root"></div>
</body>
</html>
// based on: https://github.com/chenglou/require-polyfill
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
};
function pathNormalize(path) {
var isAbsolute = path.charAt(0) === '/';
var trailingSlash = path.substr(-1) === '/';
// Normalize the path
path = normalizeArray(path.split('/').filter(function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
var globalEval = eval;
var currentScript = document.currentScript;
var projectRoot = currentScript.dataset['project-root'] || currentScript.dataset['projectRoot'] || './';
if (projectRoot == null) {
throw new Error('The attribute `data-project-root` isn\'t found in the script tag. You need to provide the root (in which node_modules reside).')
}
var nodeModulesDir = projectRoot + '/node_modules/';
var modulesCache = {};
var packageJsonMainCache = {};
var ensureEndsWithJs = function(path) {
if (path.endsWith('.js')) {
return path;
} else {
return path + '.js';
}
};
function loadScript(scriptPath) {
var request = new XMLHttpRequest();
request.open("GET", scriptPath, false); // sync
request.send();
if(request.status !== 200){ return }
var dirSeparatorIndex = scriptPath.lastIndexOf('/');
var dir = dirSeparatorIndex === -1 ? '.' : scriptPath.slice(0, dirSeparatorIndex);
var transpiledText = window.babelTransform ? babelTransform(request.responseText) : request.responseText;
var moduleText = `
(function(module, exports, modulesCache, packageJsonMainCache, nodeModulesDir) {
function require(path) {
var __dirname = "${dir}/";
var resolvedPath;
if (path.startsWith('.')) {
// require('./foo/bar')
resolvedPath = ensureEndsWithJs(__dirname + path);
} else if (path.indexOf('/') === -1) {
// require('react')
var packageJson = pathNormalize(nodeModulesDir + path + '/package.json');
if (packageJsonMainCache[packageJson] == null) {
var jsonRequest = new XMLHttpRequest();
jsonRequest.open("GET", packageJson, false);
jsonRequest.send();
var main;
if (jsonRequest.responseText != null) {
main = JSON.parse(jsonRequest.responseText).main;
};
if (main == null) {
main = 'index.js';
} else if (!main.endsWith('.js')) {
main = main + '.js';
}
packageJsonMainCache[packageJson] = nodeModulesDir + path + '/' + main;
}
resolvedPath = packageJsonMainCache[packageJson];
} else {
// require('react/bar')
resolvedPath = ensureEndsWithJs(nodeModulesDir + path);
};
resolvedPath = pathNormalize(resolvedPath);
if (modulesCache[resolvedPath] != null) {
return modulesCache[resolvedPath];
};
// initialize cache with an empty object, allows circular dependencies
modulesCache[resolvedPath] = {};
var result = loadScript(resolvedPath);
modulesCache[resolvedPath] = result;
return result;
};
var process = {env: {}, argv: []};
var global = {};
// -------Begin Require Polyfilled Module Loaded From Disk------------------------------
// file: ${scriptPath}
// root: ${projectRoot}
// ----------------------------------------------------------------------
${transpiledText}
// -------End Polyfill Loaded From Disk------------------------------
// file: ${scriptPath}
// root: ${projectRoot}
// ----------------------------------------------------------------------
return module.exports})\n//@ sourceURL=${scriptPath}`;
var module = {exports: {}};
return globalEval( moduleText )(module, module.exports, modulesCache, packageJsonMainCache, nodeModulesDir);
};
loadScript(currentScript.dataset.main || './index.js')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment