时隔半年es6module上啊
基础的写法
还是mdn清晰:
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export
// Import individual features
import { export } from "module-name";
import { export1 , export2 } from "module-name";
// Import default export
import defaultExport from "module-name";
// Import all of a module's exports as a module object
import * as name from "module-name";
// Import renamed exports
import { export as alias } from "module-name";
// Import a module for side effects only
import "module-name";
// Combinations
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
// Dynamic module import
var promise = import("module-name"); // This is a stage 3 proposal.
// Exporting individual features
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function functionName(){...}
export class ClassName {...}
// Export list
export { name1, name2, …, nameN };
// Renaming exports
export { variable1 as name1, variable2 as name2, …, nameN };
// Default exports
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// Aggregating modules 汇总页面
export * from …;
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;
export {default as none} from "./none.js";
// In parentModule.js
export { myFunction, myVariable } from 'childModule1.js';
export { myClass } from 'childModule2.js';
// In top-level module
import { myFunction, myVariable, myClass } from 'parentModule.js'
//只有一个输出简化的写法
export default foo;
import foo from 'es6-foo'
import * as fs from 'fs';
If you export default function xyz, you must import xyz or import { default as xyz }
//如果export这么写, 那么import对应的也要解构.
export {out1, out2, out3};
import {foo} from 'es6-foo'
//同样的他们都可以加as语法, 指定名字.
export {out as images};
import {foo as bar} from 'es6-foo'
//多个export
export function function1() {}
export function function2() {}
export default function1;
import defaultExport, { function1, function2 } from './module1'
If you export function xyz, you must import { xyz }
//在node里面就想引入一个文件
import router from './index.js'
//在web里面引入文件也是一样的.
import {postweb} from './node_modules/mtools/index.js';
动态引入
const m = await import('node-fetch');
const fetch=m.default;
浏览器的问题和解决
//引入端这么写:
<script type="module">
import {images} from '/show/images.js'
//输出端这么写:
//export default out;
export {
out as images
};
</script>
不要相信其他写法, 比如下面这种就怎么搞都不可以:
<script type="module" src="/show/images.js"></script>
type=module之后, 会导致html里面直接注册事件失败.
<input type="file" id="input" onchange="handleFiles(this.files)">
<script type="module">
function handleFiles() {
alert('success') //这里不会被执行.
}
</script>
我猜测原因是: 因为type=module之后就是异步加载的了, 所以input里面写的onchange就失效了, 因为函数定义并没有被提升上去.
据说是scope问题, 我再试试.
window.handlefiles=handlefiles; //这样就解决了.
正解再这里: https://stackoverflow.com/questions/44590393/es6-modules-undefined-onclick-function-after-import
然后这个讲的很清楚: https://www.contentful.com/blog/2017/04/04/es6-modules-support-lands-in-browsers-is-it-time-to-rethink-bundling/
在node端用es6 module
// package.json 里面这两个是核心内容.
{
"type": "module",
"scripts": {
"start": "node --experimental-modules ./index.js",
//这个start要这么写才行.
}
}
#发布模块, shell里面这么玩
npm publish
//package.json要指定main, 事实上下面三个字段都是必填项目
{
"name": "uds",
"version": "0.0.1",
"description": "调度算法的node版本",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node --experimental-modules ./index.js",
//这个start要这么写才行.
}
}
但是这样的情况下eslint会不通过:
#会报下面这个错.
error Parsing error: 'import' and 'export' may appear only with 'sourceType: module'
//.eslintrc.js
parserOptions: {
sourceType: 'module',
}
如果start脚本不正确, 会报错:
import mrouter from 'mrouter';
^^^^^^^
SyntaxError: Unexpected identifier
"start": "node ./index.js", //这样就会报错.
"start": "node --experimental-modules ./index.js",
如果一个模块web有node没有, 或者node有web没有, 那么如何兼容?
//要做动态引入, 比如fetch()就是web有, node没有.
if(typeof fetch ==='undefined'){
//import fetch from "node-fetch"; 这么写编译不通过, 这是静态引入.
const m = await import('node-fetch');
var fetch=m.default; //这里是m.default, 而不是m.fetch, 而且要用var, 因为要突破{}作用域.
}
单单这样还不够, 因为chrome有一个编译过程, 当他碰到import就强制检查是否(.\)满足, 所以需要隔离开. 这里错了, 改进方案再下一段.
index.js, package.json的入口js这么写
import postnode from './postnode.js'
import postweb from './postweb.js'
const mtools= function mtools(){};
export {postweb,postnode};//这里分别导出给web用的和给node用的
export default mtools;
postnode这么写, 这里不必写成这样, 改进再下一段
import post from "./postweb.js";
const postnode = async function postnode(url, content) {
const m = await import('node-fetch');
const fetch=m.default;
const showdata = await post(url, content, fetch);
return showdata; // 那么这个就是要处理展示结果集
};
export default postnode;
postweb这么写-> 改名叫postcore
const posturl = async function posturl(url, content, f) {
const response = await f(url, {
method: 'POST', // or 'PUT'
body: content, // data can be `string` or {object}!
headers: { 'Content-Type': 'application/json' },
}); // ajax拿结果
const showdata = await response.json();
return showdata; // 那么这个就是要处理展示结果集
};
export default posturl;
重大更新, 上面的结论错了. 因为我判断错了, 应该判断window, 模块化之后, 全局函数都不能直接用了.
postweb没有问题, 可以改名为postcore.
然后不论是web还是node都可以统一调用下面这个
import post from "./postcore.js";
const postnode = async function postnode(url, content) {
let fetch;
if (typeof window === "undefined") { //这里要判断window, 而不是fetch, fetch永远是不存在的.
const m = await import("node-fetch"); //node是这两行.
fetch = m.default;
}else{
// eslint-disable-next-line no-undef
fetch=window.fetch;//web是这一行
}
const showdata = await post(url, content, fetch);
return showdata; // 那么这个就是要处理展示结果集
};
export default postnode;
我错怪chrome了, chrome没有bug. 依旧是解释执行的, 之前会报引入错误, 确实是执行到了那个语句.
扩展的阅读
- chrome使用es6 module做的各种扩展:https://medium.com/front-end-weekly/es6-modules-in-chrome-extensions-an-introduction-313b3fce955b
- 如何再web使用和node一致的引入方式: http://dplatz.de/blog/2019/es6-bare-imports.html
- 作者给了5个方案, 包括: unpkg, webpack, owc, polymer, pika.
- 这里有一些参考文件: https://medium.com/@dmnsgn/es-modules-in-the-browser-almost-now-3638ffafdc68
最终结论: 不要手撸module, 痛不欲生, 用webpack可以一劳永逸的解决问题, webpack真香