在移动设备中忽略条件依赖
Posted
技术标签:
【中文标题】在移动设备中忽略条件依赖【英文标题】:Conditional dependency ignored in mobile 【发布时间】:2015-02-26 16:41:10 【问题描述】:在构建网站的过程中,我们遇到了 VideoJS 和 Angular 之间的冲突,因此当 VideoJS 库存在时,Angular 模块不会在 ios7 中加载。这是一种极端情况,页面内容比外围视频重要得多,所以我们选择只为我们的移动用户 nix VideoJS 并使用图像后备。
现在,考虑一下来自 requirejs 模块的相关代码摘录:
log("checkpoint 1");
var videojs, $ = require('jquery');
if($(".home").length && $(window).outerWidth() > 768)
log("checkpoint 2a");
videojs = require('videojs');
log("checkpoint 2b");
// video init code here
log("checkpoint 3");
在任何移动设备中,日志都会返回:
> checkpoint 1
> checkpoint 3
这表明循环没有像预期的那样在移动设备中被渗透。然而,与此相反,videojs 库仍在加载中——这违背了有条件地包含它的整个目的。
我们已经确认这是唯一包含 videojs 库的地方,因为当 videojs = require('videojs');
被注释掉时问题就消失了 - 该库没有出现在资源列表中,并且页面正常呈现。
我们只是在设置条件依赖时很差吗?是否有其他方法可以执行此操作,或者我们是否牢牢卡在 Require 的已知限制中?
【问题讨论】:
【参考方案1】:videojs = require('videojs')
我敢打赌,这是源代码(非编译文件)中的一行,然后您使用 browserify(或发布应用程序之前的类似内容)进行编译。
当然,问题是您编译的文件总是需要 videojs(除非该行被注释掉),因为您的条件基于仅在运行时可用的行列式,而不是编译时。
所以,回答你的问题:
我们只是设置条件依赖关系不好?
是的。
可能有很多方法可以做到这一点,但我想到的一种是将 videojs 库作为单独的资产提供服务。您将使用(呃)用户代理解析来确定设备是否正在运行 iOS7
类似于以下内容(php 示例):
<?php if(!is_ios7()) //pseudo code - UA parsing in here. ?>
<script src="/path/to/videojs"></script>
<?php ?>
然后在您的主 js 文件中,您可以检测是否存在 videojs 全局变量,然后在需要时使用它。
【讨论】:
【参考方案2】:对于生产和测试 ENV 以及移动/桌面版本使用可以使用这个加载器:(来自这个 git hub 项目https://github.com/BoilerplateMVC/Marionette-Require-Boilerplate/blob/master/public/index.html)
// Mobile/Desktop Detection script
(function(ua, w, d, undefined)
// App Environment
// ---------------
// Tip: Set to true to turn on "production" mode
var production = true,
filesToLoad,
//BoilerplateMVC Helper Methods
boilerplateMVC =
loadCSS: function(url, callback)
var link = d.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
d.getElementsByTagName("head")[0].appendChild(link);
if(callback)
callback();
,
loadJS: function(file, callback)
var script = d.createElement("script");
script.type = "text/javascript";
if (script.readyState) // IE
script.onreadystatechange = function()
if (script.readyState == "loaded"
|| script.readyState == "complete")
script.onreadystatechange = null;
callback();
;
else // Other Browsers
script.onload = function()
callback();
;
if(((typeof file).toLowerCase()) === "object"
&& file["data-main"] !== undefined)
script.setAttribute("data-main",
file["data-main"]);
script.async = true;
script.src = file.src;
else
script.src = file;
d.getElementsByTagName("head")[0].appendChild(script);
,
loadFiles: function(production, obj, callback)
var self = this;
if(production)
// Loads the production CSS file(s)
self.loadCSS(obj["prod-css"], function()
// If there are production JavaScript files to load
if(obj["prod-js"])
// Loads the correct initialization file (which includes Almond.js)
self.loadJS(obj["prod-js"], callback);
);
else
// Loads the development CSS file(s)
self.loadCSS(obj["dev-css"], function()
// If there are development Javascript files to load
if(obj["dev-js"])
// Loads Require.js and tells Require.js to find the correct intialization file
self.loadJS(obj["dev-js"], callback);
);
;
// Mobile/Tablet Logic
if((/iPhone|iPod|iPad|android|BlackBerry|Opera Mini|IEMobile/).test(ua))
// Mobile/Tablet CSS and JavaScript files to load
filesToLoad =
// CSS file that is loaded when in development mode
"dev-css": "css/mobile.css",
// CSS file that is loaded when in production mode
"prod-css": "css/mobile.min.css",
// Require.js configuration file that is loaded when in development mode
"dev-js": "data-main": "js/app/config/config.js", "src": "js/libs/require.js" ,
// JavaScript initialization file that is also loaded when in development mode
"dev-init": "js/app/init/MobileInit.js",
// JavaScript file that is loaded when in production mode
"prod-init": "js/app/init/MobileInit.min.js",
"prod-js": "data-main": "js/app/config/config.js", "src": "js/libs/require.js"
;
// Desktop Logic
else
// Desktop CSS and JavaScript files to load
filesToLoad =
// CSS file that is loaded when in development mode
"dev-css": "css/desktop.css",
// CSS file that is loaded when in production mode
"prod-css": "css/desktop.min.css",
// Require.js configuration file that is also loaded when in development mode
"dev-js": "data-main": "js/app/config/config.js", "src": "js/libs/require.js" ,
// JavaScript initialization file that is loaded when in development mode
"dev-init": "js/app/init/DesktopInit.js",
// JavaScript file that is loaded when in production mode
"prod-init": "js/app/init/DesktopInit.min.js",
"prod-js": "data-main": "js/app/config/config.js", "src": "js/libs/require.js"
;
boilerplateMVC.loadFiles(production, filesToLoad, function()
if(!production && window.require)
require([filesToLoad["dev-init"]]);
else if ( production )
require([filesToLoad["prod-init"]])
);
)(navigator.userAgent || navigator.vendor || window.opera, window, document);
以及该项目中的其他逻辑:
var App = new Backbone.Marionette.Application();
function isMobile()
var userAgent = navigator.userAgent || navigator.vendor || window.opera;
return ((/iPhone|iPod|iPad|Android|BlackBerry|Opera Mini|IEMobile/).test(userAgent));
App.mobile = isMobile();
require(["App", "jquery", "routers/AppRouter", "controllers/MobileController", "backbone", "marionette", "jquerymobile", "backbone.validateAll"],
function (App, $, AppRouter, AppController)
// Prevents all anchor click handling
$.mobile.linkBindingEnabled = false;
// Disabling this will prevent jQuery Mobile from handling hash changes
$.mobile.hashListeningEnabled = false;
App.appRouter = new AppRouter(
controller:new AppController()
);
App.start();
);
【讨论】:
以上是关于在移动设备中忽略条件依赖的主要内容,如果未能解决你的问题,请参考以下文章