什么是模块?
模块的组成
我们,通常说的模块化,其实是指js的模块化。现在流行的模块化规范有以下几种:CommonJs、AMD、CMD、ES6模块化。本篇文章,我们来介绍下CommonJS以及ES6模块化相关的知识,其余两种大家自行了解。
下面以一个案例来解释下:
首先我们创建一个文件夹来存放测试代码,然后cd到该目录里面,使用npm init命令初始化一个工程,这样就会自动生成package.json文件。之后,分别创建3个js文件来测试。
module.exports = {
foo() {
console.log('moudle1 foo()')
},
a:10
}
//如果一个文件中有两个module.exports,下面的会覆盖上面的
// module.exports={
// a:10
// }
module.exports = function () {
console.log('module2()')
}
exports.foo = function () {
console.log('module3 foo()')
}
exports.bar = function () {
console.log('module3 bar()')
}
在app.js文件中引入模块
let module1 = require('./modules/module1')
let module2 = require('./modules/module2')
let module3 = require('./modules/module3')//等价于require('./modules/module3.js'),js可以省略
module1.a
console.log(module1.a)
module2()
module3.bar()
最后,我们使用node命令执行app.js文件,发现原本写在module1.js、module2.js、module3.jsi里面的逻辑成功执行了,说明这3个模块确实被导入app.js中了。
接下来,有一个问题了,刚刚我们是使用node来执行js文件的,如果我们直接用浏览器执行app.js文件是会报错的,因为浏览器只认识js代码,require这些关键字浏览器是不认识的。例如,我们新建一html文件,然后用浏览器执行这个html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="app.js"></script>
</body>
</html>
如果我们想要使用浏览器来执行app.js该怎么办呢?这就需要另一个工具——browserify
. 下载browserify
-dev表示,我们只是在开发环境中需要browserify,生产环境是不需要browserify,因为生产环境已经是运行在浏览器中的。
执行了上面两句代码之后,package.json中就会有browserify的依赖
{
"name": "modulejstest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"browserify": "^17.0.0"
}
//如果不加-dev,那么browserify依赖在dependencies闭包下,加了就在devDependencies闭包下
// "dependencies": {
// "browserify": "^17.0.0"
// }
}
最后,我们执行如下命令:然后引入bundle.js文件到html中,这样浏览器就不会报错了。
browserify app.js -o dist/bundle.js
相比起CommonJs,es6的模块化就十分的简单了,首先我们需要安装几个工具:
安装babel-cli, babel-preset-es2015和browserify
在工程根目录下定义.babelrc文件
{
"presets": ["es2015"]
}
export function foo() {
console.log('module1 foo()');
}
export let bar = function () {
console.log('module1 bar()');
}
export const DATA_ARR = [1, 3, 5, 1]
let data = 'module2 data'
function fun1() {
console.log('module2 fun1() ' + data);
}
function fun2() {
console.log('module2 fun2() ' + data);
}
export {fun1, fun2}
//一个文件只能由一个export default
export default {
name: 'Tom',
setName: function (name) {
this.name = name
}
}
在app.js文件中引入上述文件
import {foo,DATA_ARR}from './module1'
import { fun1,fun2 } from './module2'
import test from'./module3' //使用export default暴露的模块不用写{},任意取个名字即可
foo()
fun1()
fun2()
console.log("test--->"+test.name)
test.setName("brett")
console.log("test--->"+test.name)
console.log(DATA_ARR)
注意:如果要使用node执行js文件必须使用babel进行编译,否则会报错的,如果要在浏览器执行js代码,除了使用babel编译外,还要使用Browserify编译。
工程目录如下: