TL;博士;你应该如何加载多个webpack包而不用脚本标签乱丢你的代码
我一直在考虑使用webpack,但是在加载webpack包时似乎有一件我不知道的东西,到目前为止我一直在使用requirejs,它允许你将代码分成模块(我认为它相当于webpack中的bundle)但是requirejs允许你在代码中按名称要求脚本然后映射到配置中的url但是使用webpack你只需要在页面上包含一个脚本标记,感觉就像它可以很容易失控,因为你最终会在应用程序的整个视图中散落乱码,并且更难以切换捆绑包而不是更新单个URL,而是需要查找并替换该URL的每个出现,而不是世界末日,但似乎我错过了一些功能,以使这更容易,或者它是requirejs和webpack之间的公认差异。
我应该提一下我没有考虑添加webpack的代码库是单页应用程序所以也许webpack不适合这种环境吗?
只是为我想要包含的内容添加一些上下文,我们的服务器端代码使用mvc模式,所以它看起来像这样
<html>
<head><!-- stuff here --></head>
<body>
<!-- some included view here -->
</body>
</html>
<div>
<!-- ... -->
<!-- Currently it has this -->
<script>
require(['something'], function(s){ /* new s(); */ /* s(); */ /* etc */ });
</script>
<!-- and i'd imagine it would be like this with webpack -->
<script src="my_bundle.js"></script>
</div>
<div>
<!-- ... -->
<!-- Currently it has this -->
<script>
require(['something', 'another_thing'], function(s){ /* new s(); */ /* s(); */ /* etc */ });
</script>
<!-- and i'd imagine it would be like this with webpack -->
<script src="my_bundle.js"></script>
<script src="my_bundle2.js"></script>
</div>
答案 0 :(得分:2)
最近,我在单页应用程序中使用了webpack的code splitting功能,根据路由动态加载bundle。这不需要您在整个应用程序中丢弃脚本标记。如果使用任何排序的路由机制,则可以在访问该路由时动态导入依赖关系,如下所示:
// Index
router.on(() => {
import(/* webpackChunkName: "routeA" */ '../routes/routeA').then((module) => {
// do something with your loaded module
}).resolve();
});
Dynamically loading这个“root”样式模块,即webpack捆绑的依赖树的根,意味着你只能在需要时获取它。这意味着客户端只会在执行此路由时获取此bundle.js.
使用动态导入需要在webpack配置中添加chunkFilename
属性:
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
编辑:如果您正在使用express.js,您可以按照其路由机制执行相同的操作。您最好的选择是参考webpack提供的代码拆分文档(上面链接)。
答案 1 :(得分:0)
我对路由器方法并不完全满意,因为它有效地意味着必须在javascript中复制我们的url重写配置并复制页面共享代码的import语句,我不确定但是import docs似乎意味着任何导入的脚本都将包含在最终的包中,而不是在页面加载期间动态加载,这意味着捆绑中的大量代码在大多数时间都是未使用的。
对我来说,最好的方法似乎是有效地创建一个更简单的requirejs版本来加载bundle文件(例如下面的例子),这样我就可以保留与现有代码类似的结构,不可否认我仍然可以寻找一个库而不是滚动我自己的装载机,但我还没有决定。class Loader{
constructor(config){
this.config = config;
}
load(modName){
if(this.config.debug)console.log('loader - ', 'load called', arguments);
if(!document.getElementById(modName)){
if(this.config.debug)console.log('loader - ', 'loading new script', modName, this.config.map[modName]);
var script = document.createElement('script');
script.id = modName;
script.type = 'text/javascript';
script.src = this.config.map[modName];
script.async = true;
document.head.appendChild(script);
}
}
}
export default Loader;
window.loader = new Loader({
'debug': true,
'map': {
'something': '/scripts/bundle.js',
'another_thing': '/scripts/bundle2.js'
}
});
<div>
<!-- ... -->
<!-- Currently it has this -->
<script>
require(['something'], function(s){ /* new s(); */ /* s(); */ /* etc */ });
</script>
<!-- which would change to (any of the callback code would be inside the bundle) -->
<script>
window.loader.load('something');
</script>
</div>