`
seavers
  • 浏览: 173263 次
  • 来自: ...
社区版块
存档分类
最新评论

mini javascript loader

阅读更多

自己写的一个mini 且 simple 的 javascript loader

功能特点
  • 异步并行载入js, 每个js只加载一次
  • 支持模块依赖, 未检测循环依赖
  • 支持别名
  • 兼容ie6+ , firefox, chrome ...
  • API : 
  •     define.alias['modName'] = 'http://path/to/mods/root/dir'
        define(deps, callback)   其中 callback(dep1, dep2, dep3...)
        require(deps, callback)   其中 callback(dep1, dep2, dep3...)




define = (function() {
	
	var modules = {};
	var modulesCallbacks = {};
	var alias = window.alias || {};

	function map(arr, callback) {
		var ret = [];
		for(var i = 0; i < arr.length; i++) {
			ret.push(callback(arr[i], i, arr));
		}
		return ret;
	}
	function isString(obj) {
		return typeof(obj) == 'string';
	}
	function isArray(obj) {
		return Object.prototype.toString.call(obj) == '[object Array]';
	}
	function isFunction(obj) {
		return typeof(obj) == 'function';
	}
	function mix(src, dst) {
		for(var key in dst) {
			src[key] = dst[key];
		}
	}
	function getScript(url, callback) {
		var node = document.createElement("script");
		node.async = true;
		if (document.addEventListener) {
			node.addEventListener('load', callback);
		} else {
			node.onreadystatechange = function () {
				if(node.readyState == 'loaded' || node.readyState == 'complete') {
					callback && callback();
				}
			}
		}
		node.src = url;

		var head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
		head.insertBefore(node, head.firstChild);
		return node;
	}

	function getCurrentScript() {
		
		//firefox4 and opera
		if (document.currentScript) {
			return document.currentScript;
		} else if (document.attachEvent) {
			//ie6-9 得到当前正在执行的script标签
			var scripts = document.getElementsByTagName('script');
			for (var i = scripts.length - 1; i > -1; i--) {
				if (scripts[i].readyState === 'interactive') {
					return scripts[i];
				}
			}
		} else {
			// 参考 https://github.com/samyk/jiagra/blob/master/jiagra.js
			// chrome and firefox4以前的版本
			var stack;
			try {
				makeReferenceError
			} catch (e) {
				stack = e.stack;
			}
			if (!stack)
				return undefined;
			// chrome uses at, ff uses @

			var e = stack.indexOf(' at ') !== -1 ? ' at ' : '@';
			while (stack.indexOf(e) !== -1) {
				stack = stack.substring(stack.indexOf(e) + e.length);
			}
			stack = stack.replace(/:\d+:\d+$/ig, "");

			var scripts = document.getElementsByTagName('script');
			for (var i = scripts.length - 1; i > -1; i--) {
				if (scripts[i].src === stack) {
					return scripts[i];
				}
			}
		}
	}

	function getScriptWithCache(url, callback) {
		var scripts = this._scripts = this._scripts || {};
		var cache = scripts[url];
		if (cache === true) {
			callback && callback();
			return ;
		} else if (isArray(cache)) {
			cache.push(callback);
			return ;
		} else {
			scripts[url] = [callback];
		}

		getScript(url, function() {
			var callbacks = scripts[url] || [];
			scripts[url] = true;
			for(var i = 0; i < callbacks.length; i++) {
				callbacks[i] && callbacks[i]();
			}
		});		
	}

	function getModule(mod, callback) {
		if (!modules[mod]) {
			modulesCallbacks[mod] = modulesCallbacks[mod] || [];
			modulesCallbacks[mod].push(callback);

			getScriptWithCache(mod);
		} else {
			callback && callback(modules[mod]);
		}
	}

	function getModules(mods, callback) {
		if (mods == undefined || mods.length == 0) {
			callback && callback();
			return ;
		}
		var c = 0;

		var ret = [];
		map(mods, function(mod, i) {
			getModule(mod, function(obj) {
				ret[i] = obj;

				if (++c == mods.length) {
					callback && callback(ret);
				}
			});
		});
	}

	function define(deps, callback) {
		var container = this;

		if (!isString(deps) && !isArray(deps)) {
			callback = deps;
			deps = [];
		}
		var current = getCurrentScript();
		var url = current && current.src;

		deps = deps || [];
		if (isString(deps)) {
			deps = deps.split(',');
		}
		var allDeps = map(deps, tran);				//全部转换映射

		getModules(allDeps, function(mods) {
			var ret = isFunction(callback) ? callback.apply(undefined, mods||[]) : callback;
			modules[url] = modules[url] || {}
			mix(modules[url], ret);

			container != window && (mix(container, ret));

			if (modulesCallbacks[url]) {
				for(var i = 0; i < modulesCallbacks[url].length; i++) {
					modulesCallbacks[url][i](ret);
				}
			}
		});

		return container;
	}

	function tran(dep) {
		for(var key in alias) {
			dep = dep.replace(new RegExp('^' + key), alias[key]);		//TODO
		}
		return dep + '.js';
	}

	define.alias = alias;
	return define;
})();









测试用例

//上述代码保存为 http://localhost/loader/loader.js


<!-- index.htm -->
<script src="loader.js"></script>

<script>
define.alias['ok'] = 'http://localhost/loader/';
define(['ok/mod1', 'ok/mod2'], function(Mod1, Mod2) {
	console.log('execute index ', Mod1, Mod2);
});
</script>






//   http://localhost/loader/mod1.js
require(['ok/mod2'], function(Mod2) {
	console.log('mod1 index ', Mod2);

	return {
		mod1: 'this is mod1'
	}
});




//   http://localhost/loader/mod2.js
define(function() {
	console.log('mod2 index ');

	return {
		'hello' : 'world'
	}
});






补: 其它用法
//mod3.js
//功能模块1
define({
    sayHello : function() {
       console.log('hello');
    }
});

//功能模块2, 模块2没支持!!!
define(function() {
    return {
        sayWorld : function() {
           console.log('world');
        }
    }
});





App = {define : define, require: define};
App.define.alias['ok'] = 'http://lhj/loader';
App.define({
      showMsg : function(msg) {
          console.log(msg);
      }
});

App.define(function(Mod3) {
      return {
          say : function() {
				App.require('ok/Mod3', function(Mod3) {
	                  return Mod3.sayHello() + ' ' + '';//Mod3.sayWorld();
				});
          }
      }
});

App.showMsg(123);
App.say();


分享到:
评论

相关推荐

    mini-program-webpack-loader:基于 webpack 的小程序构建工具

    mini-program-webpack-loader基于 webpack 4.0 的小程序打包工具。项目依赖 async/await, Set/Map, spread 等 es6+ 语法安装 $ npm i mini-program-webpack-loader --dev介绍该工具主要解决小程序难以集成更多的成熟...

    node-sass 4.12、4.14.1、5 node-sass-loader node_modules 安装包

    当Webpack遇到Sass文件时,Sass-Loader会先调用Node-Sass将Sass编译成CSS,然后可能再经过其他CSS处理加载器(如CSS-Loader、Mini-CSS-Extract-Plugin等)进行模块化处理和压缩。 **安装与使用** 要在项目中使用...

    webpack的Sassloader用于将Sass编译成CSS

    1. **分离CSS**:使用`mini-css-extract-plugin`将CSS提取到单独的文件中,提高页面加载性能。 2. **优化加载顺序**:根据加载速度和依赖关系,合理调整加载器的顺序。 3. **使用Sass的特性**:Sass提供了许多CSS...

    【JavaScript源代码】webpack拆分压缩css并以link导入的操作步骤.docx

    npm install --save-dev webpack webpack-cli css-loader style-loader mini-css-extract-plugin html-webpack-plugin # 或者使用 yarn yarn add --dev webpack webpack-cli css-loader style-loader mini-css-...

    vue框架下的webpack包的使用,里面涉及html, css, JavaScript代码.zip

    - `babel-loader`是Webpack处理JavaScript的关键,它将ES6+语法转换为浏览器可识别的ES5语法。 - `eslint-loader`可以集成ESLint进行代码质量检查,确保代码风格统一。 6. **模块化开发** - Vue的单文件组件(SFC...

    前端开源库-vision-css-loader

    它可以在CSS文件被其他加载器(如style-loader或mini-css-extract-plugin)处理之前,添加视觉相关的元数据或者进行预处理。 2. **CSS解析与增强**: `vision-css-loader`解析CSS文件,识别选择器、属性和值,并...

    深入webpack打包原理及loader和plugin的实现

    1. **实现Loader**:要实现一个Loader,首先需要编写一个JavaScript模块,该模块导出一个函数。该函数接收源文件内容作为参数,并返回转换后的内容。比如一个简单的loader示例: ```javascript module.exports = ...

    最新大厂前端面试题-面试指南webpack篇.docx

    Loader 主要用于将非 JavaScript 文件转换为 JavaScript 文件,而 Plugin 则是扩展 Webpack 的功能,可以在构建过程中改变结果。Loader 是一种转换函数,而 Plugin 是一种插件,可以监听 Webpack 的生命周期事件,并...

    webpack与SPA实践之管理CSS等资源的方法

    对于非 JavaScript 模块,如 CSS,webpack 需要借助加载器(Loader)来转换它们为可处理的 JavaScript 模块。 对于 CSS 的处理,webpack 提供了 style-loader 和 css-loader 这两个加载器。style-loader 负责将 CSS...

    基于miniprogramwebpackloader的小程序脚手架

    【压缩包子文件的文件名称列表】:mini-program-webpack-loader-boilerplate-master 这个压缩包很可能包含了整个小程序脚手架的源代码,包括Webpack的配置文件(如webpack.config.js),Babel的配置(如.babelrc或...

    cssliteralloaderwebpack装入器用于提取和处理在其他文件中定义的CSS

    在这个例子中,`css-literal-loader`首先处理CSS字面量,然后`mini-css-extract-plugin.loader`将CSS提取到外部文件,接着`css-loader`和`postcss-loader`分别处理CSS模块化和应用PostCSS插件。 总之,`css-literal...

    svgo-loader::framed_picture::evergreen_tree:常绿svgo-loader更换

    用于webpack的svgo加载程序 @hyperbola/svgo-loader是零依赖性,常绿替代 。...带有asset模块const svgToMiniDataURI = require ( "mini-svg-data-uri" ) ;module . exports = { ... , module : { rules : [ { test :

    webpack管理资源demo

    此外,还可以结合`postcss-loader`进行CSS预处理器(如Sass、Less)的支持,以及使用`mini-css-extract-plugin`提取CSS到单独的文件,优化生产环境的性能。 2. **加载images**: 对于图片资源,我们可以使用`url-...

    mini-css-extract-plugin-NS-bug

    其中,`mini-css-extract-plugin`是Webpack中一个非常实用的插件,它负责从JavaScript模块中提取CSS到单独的文件,以实现CSS的异步加载和更好的缓存策略。然而,如同任何技术一样,`mini-css-extract-plugin`也存在...

    详解vue-loader在项目中是如何配置的

    const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { // other options... module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { extractCSS: true, ...

    **webpack 基本使用**

    - **提取 CSS 成单独文件**:使用 `mini-css-extract-plugin` 插件来提取 CSS 到单独的文件中。 - **CSS 兼容性处理**:可以使用 `postcss-loader` 结合 `autoprefixer` 自动添加浏览器前缀。 - **CSS 压缩**:...

    webpack-ExtractTextPlugin

    `ExtractTextWebpackPlugin` 是 Webpack 的一个插件,它的主要作用是将原本由 Style Loader 处理的 CSS 内容提取到一个单独的文件中,而不是将其插入到 JavaScript 文件中。这样做的好处包括: 1. **提高首屏加载...

    【webpack基础】Webpack 常用命令总结

    ESLint-Loader可以在打包前检查JavaScript代码的语法和风格一致性,提高代码质量。 #### 四、常用插件安装 **HTMLWebpackPlugin** ``` npm install html-webpack-plugin --save-dev ``` 此插件可以自动生成HTML...

    babel7.x和webpack4.x配置vue项目的方法步骤.docx

    7. `babel-loader`:Webpack加载器,将JavaScript文件通过Babel进行转换。 安装这些依赖后,你需要在项目根目录创建或更新`webpack.config.js`文件来定义Webpack的配置。配置文件通常包括入口、输出、模块规则...

    从零搭建webpack4

    npm install --save-dev mini-css-extract-plugin terser-webpack-plugin ``` 更新`webpack.config.js`中的配置以启用这些优化。 ### 8. 多页面应用配置 对于多页面应用,需要在entry中配置多个入口,并根据需求...

Global site tag (gtag.js) - Google Analytics