ES module っていつ使えるんだろう
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ 早く使いたい
import とか export とか
複数ページの共通部分とか 綺麗に切り離したい いかにもモジュールっぽい部分とか ファイル分割したいことってあります
いまの仕組みだと HTML のほうに script タグを大量に書かないとだめなので module 使えるようになってほしいなぁと思います
いまのところ いろいろぐぐってみても chromium のほうでも実装されたとか聞かないですし そもそも他の ES6 とは別扱いされてる感があります
ES6 の compat table にも載っていないです
さらに 少し前に ES module は特殊で実装的に決まってないような事が多くてどうこう とか Node.js の require の仕様とのどうこうとか そんなのを聞いた気がするのでこれまでの ES6 が次々使えるようになってたようにはいかなそうです
でも module ごとにファイルロードしてグローバルにいろいろあるのも嫌なので module ぽいことをできるようにこんなのを準備してみました
[module.js]
[test.js]
[test2.js]
[main.html]
ロードするときは Module.load を使います
module になるファイルは全体を !function(){} で囲んでグローバルに何も置かないようにして Module.set でセットします
読み込みは非同期なので Module.load や Module.getAsync で受け取る Promise を使います
Module.get はすでにロードされていないとエラーになるので
はエラーになることがあります
勢いで作ってはみたけど ロード済みじゃないと非同期になって書きづらいし もっと ES module に近い書き方なようにしておいたほうが 後からちゃんとした ES module に移行するときが楽かも
複数ページの共通部分とか 綺麗に切り離したい いかにもモジュールっぽい部分とか ファイル分割したいことってあります
いまの仕組みだと HTML のほうに script タグを大量に書かないとだめなので module 使えるようになってほしいなぁと思います
いまのところ いろいろぐぐってみても chromium のほうでも実装されたとか聞かないですし そもそも他の ES6 とは別扱いされてる感があります
ES6 の compat table にも載っていないです
さらに 少し前に ES module は特殊で実装的に決まってないような事が多くてどうこう とか Node.js の require の仕様とのどうこうとか そんなのを聞いた気がするのでこれまでの ES6 が次々使えるようになってたようにはいかなそうです
でも module ごとにファイルロードしてグローバルにいろいろあるのも嫌なので module ぽいことをできるようにこんなのを準備してみました
[module.js]
Module = {
modules: {},
promises: {},
load(name, opt){
name = this._nameOptimize(name)
opt = opt || {}
var url = opt.url || name + ".js"
var max_wait = ~~max_wait
if(!(name in this.modules)){
var s = document.createElement("script")
s.async = false
s.src = url
document.head.appendChild(s)
var promise = this._createOpenPromise()
max_wait > 0 && setTimeout(reject, max_wait)
this.promises[name] = promise
}
return this.promises[name]
},
set(name, m){
name = this._nameOptimize(name)
if(name in this.modules){
return true
}else{
this.modules[name] = m
this.promises[name] && this.promises[name].resolve(m)
return false
}
},
get(name){
name = this._nameOptimize(name)
if(!(name in this.modules)) throw new Error(name + " is not loaded")
return this.modules[name]
},
getAsync(name, max_wait){
name = this._nameOptimize(name)
return this.promises[name]
},
_createOpenPromise(){
var aa, bb
var p = new Promise((a,b) => {aa = a, bb = b})
p.resolve = aa
p.reject = bb
return p
},
_nameOptimize(name){
name = name.trim()
if(name.endsWith(".js")){
name = name.substr(0, name.length - 3)
}
return name
}
}
modules: {},
promises: {},
load(name, opt){
name = this._nameOptimize(name)
opt = opt || {}
var url = opt.url || name + ".js"
var max_wait = ~~max_wait
if(!(name in this.modules)){
var s = document.createElement("script")
s.async = false
s.src = url
document.head.appendChild(s)
var promise = this._createOpenPromise()
max_wait > 0 && setTimeout(reject, max_wait)
this.promises[name] = promise
}
return this.promises[name]
},
set(name, m){
name = this._nameOptimize(name)
if(name in this.modules){
return true
}else{
this.modules[name] = m
this.promises[name] && this.promises[name].resolve(m)
return false
}
},
get(name){
name = this._nameOptimize(name)
if(!(name in this.modules)) throw new Error(name + " is not loaded")
return this.modules[name]
},
getAsync(name, max_wait){
name = this._nameOptimize(name)
return this.promises[name]
},
_createOpenPromise(){
var aa, bb
var p = new Promise((a,b) => {aa = a, bb = b})
p.resolve = aa
p.reject = bb
return p
},
_nameOptimize(name){
name = name.trim()
if(name.endsWith(".js")){
name = name.substr(0, name.length - 3)
}
return name
}
}
[test.js]
!function(){
var printTest = function(s){
console.log("test", s)
}
var printTest2 = function(s){
console.log("test2", s)
}
Module.set("test", {
printTest,
printTest2
})
}()
var printTest = function(s){
console.log("test", s)
}
var printTest2 = function(s){
console.log("test2", s)
}
Module.set("test", {
printTest,
printTest2
})
}()
[test2.js]
!function(){
Module.set("test2", function(s){
console.log("test", s)
})
}()
Module.set("test2", function(s){
console.log("test", s)
})
}()
[main.html]
<script src="module.js"></script>
<script>
Module.load("test")
</script>
<script>
Module.get("test").printTest(1)
Module.load("test2").then(tes => tes(2))
Module.getAsync("test2").then(tes => tes(3))
</script>
<script>
Module.load("test")
</script>
<script>
Module.get("test").printTest(1)
Module.load("test2").then(tes => tes(2))
Module.getAsync("test2").then(tes => tes(3))
</script>
test 1
test 2
test 3
test 2
test 3
ロードするときは Module.load を使います
module になるファイルは全体を !function(){} で囲んでグローバルに何も置かないようにして Module.set でセットします
読み込みは非同期なので Module.load や Module.getAsync で受け取る Promise を使います
Module.get はすでにロードされていないとエラーになるので
Module.get("test").printTest(1)
はエラーになることがあります
勢いで作ってはみたけど ロード済みじゃないと非同期になって書きづらいし もっと ES module に近い書き方なようにしておいたほうが 後からちゃんとした ES module に移行するときが楽かも