模块化
当下最重要的前端开发范式之一;将代码按照功能的不同,划分为不同的模块,单独维护,提高开发效率,降低维护成本;模块化仅仅是一个思想
模块化的演变过程
-
文件划分方式
- 缺点: 1、污染全局作用域;2、命名冲突问题;3、无法管理模块依赖关系 命名空间方式
- 缺点:1、模块成员任然可以在外部被访问、被修改;2、模块的依赖关系也没有解决 IIFE
模块化规范的出现
模块化标准+模块化加载器
-
模块化规范
-
- CommonJs规范(以同步的方式加载模块):nodeJs提出的标准:;1、一个文件就是一个模块;2、每个模块都有单独的作用域;3、通过module.exports导出成员;4、通过require函数载入模块
-
- AMD(Asynchronous Module Definition):异步的模块定义规范;Require.js库,实现AMD规范,本身也是一个非常强大的模块加载器;1、约定每一个模块都用define这个函数去
定义
;默认接收两个参数,也可以传递三个参数;第一个参数是模块的名字,第二个参数是一个数组,声明模块的依赖项,第三个参数是一个函数,函数的参数与前面的依赖项一一对应;return实现导出;2、require函数:用来自动加载
模块,
- AMD(Asynchronous Module Definition):异步的模块定义规范;Require.js库,实现AMD规范,本身也是一个非常强大的模块加载器;1、约定每一个模块都用define这个函数去
-
- 淘宝推出的Sea.js+CMD;类似CommonJS规范
目前绝大多数的第三方库都支持AMD规范
-
AMD缺点
- 使用起来相对复杂
- 模块JS文件请求频繁
模块化标准规范
-
模块化的最佳实践
-
- 我们在nodeJS环境中会去遵循CommonJS规范去组织模块(内置的环境系统);
-
- 在浏览器环境当中,采用ES Module规范(ES6中定义的模块系统),存在环境兼容问题;随着webpack等一系列的打包工具的流行,逐渐开始普及;现在绝大多数浏览器已经开始支持ES Module
ES Modules基本特性
//大多数浏览器支持ES Module,所以type属性设置为module就可以正常使用
<script type="module"></script>
通过serve .可以启动项目在浏览器进行查看;安装serve的命令:npm i serve -g
- 自动采用严格模式,不加‘use strict’也是严格模式;严格模;式不能在全局范围直接使用this;
- 每个ESM模块都是单独的私有作用域
<script type="module"></script>
就是一个 - 通过CORS去请求外部JS模块,服务端支持CORS才可以通过script请求
- ESM的script标签会延迟执行脚本;网页渲染完成再去执行脚本,不会阻碍页面元素的显示,相当于
<script defer></script>
ES Modules导出和导入
export模块内对外暴露接口
import模块内导入其他模块
//./module.js
const foo='es modules'
export {foo}
//或
export const name='123'
//或
export {name,hello,Person}
/*导出并重命名
如果重命名的名称为default就是默认导出导入的时候必须重命名
import {default as fooName} from './module.js'
也可以直接import abc from './module.js'
*/
export {
name as fooName
}
//./app.js
import {foo} from './module.js'
console.log(foo)//=> es modules
安装Browser Sync(具有热更新的web server)
运行当前目录并监视所有的JS文件:命令:browser-sync . --files **/*.js
-
注意事项:
-
- export单独使用的时候,必须要有花括号,后面不是字面量对象,是固定的语法
-
- export default 后面导出的是字面量对象,export default {name,age}
-
- 模块的外部不能修改成员,导入的成员是只读成员;导出的成员不是字面量对象,导入的成员也不是解构,只是一种语法;模块修改会受到影响
导入用法
import用法
import {name} from './module.js'
//必须要有完整的文件名称,如:.js,与CommonJs有区别,打包模块时,可以省略
//相对路径的./不能省略,以字母开头会以为加载的是第三方模块
//可以使用绝对路径和完整的url
//--------------------------------------------------------------------
//加载这个模块并不提取它
import {} from './module.js'
import './module.js'
//--------------------------------------------------------------------
//使用*将模块中的所有成员提取出来,使用as将提取出来的成员放到mod对象中
import * as mod from './module.js'
//--------------------------------------------------------------------
//在不确定模块路径或者需要判断的时候不能使用import,只能出现在最顶层最外层
import('./module.js').then(function(module){
console.log(module)
})
//--------------------------------------------------------------------
//同时导出命名成员和默认成员
import {name,age,default as title} from './module.js'
import title,{name,age} from './module.js'
导出导入成员
//在一个文件中到处所有的文件,因为它只是一个桥梁的作用
export {Button} from './button.js'
export {Avatar} from './avatar.js'
//有默认模块,要起名字
注:如果中间导出的文件里面有默认成员,要给他起名字
ES Modules浏览器环境 Polyfil
ie浏览器不支持ES Module,所以需要引入polyfill
//promise的
<script nomodule src="http://unpkg.com/promise-polyfill@8.1.3/dist/polyfill.min.js"></script>
//babel
<script nomodule src="http://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
<script nomodule src="http://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
//生产环境一般不这样用,加载时间会比较长
ES Modules in Node.js - 支持情况
只要node版本大于8.5
在node环境中直接使用ES Modules
- 将文件的扩展名js改为mjs
- 启用文件 node --experimental-module index.mjs
不支持import {camelCase} from ‘lodash’
因为第三方模块都是到处默认成员
内置模块兼容了ESM的提取成员方式如:fs
-
与CommonJS交互
- 1.ES Module中可以导入CommonJS模块,不能直接提取成员,注意import不是解构导出对象
- 2.CommonJS模块始终只会导出一个默认成员,不能在CommonJS模块中通过 require 载入ES Module Babel兼容方案
- yarn add @babel/node @babel/core @babel/preset-env --dev
webpack打包
打包工具(前端整体的模块化)
- 模块打包器(Module bundler)
- 模块加载器(Loader)
- 代码拆分(Code Splitting)
- 资源模块(Asset Module)
npm i serve -g 安装serve依赖,在页面直接运行项目 serve .
yarn init --yes 安装package.json
yarn add webpack webpack-cli --dev 安装no-module
yarn webpack 打包 更改script里面的路径 dist/main.js 去掉type=‘module’
-
webpack配置文件
- 在根目录上添加webpack.config.js文件
const path = require('path')
module.exports = {
entry: './src/main.js',//打包入口路径
output: {//输出文件路径的位置,是一个对象
filename: 'bundle.js',
path: path.join(__dirname, 'output')
}
}
-
webpack工作模式
- yarn webpack --mode development (开发模式)
- yarn webpack --mode none (最原始的打包模式)
- 或者在webpack.config.js中添加
module.exports = {
entry: './src/main.js',//打包入口路径
mode: 'development',//none
output: {//输出文件路径的位置,是一个对象
filename: 'bundle.js',
path: path.join(__dirname, 'output')
}
}
前端工程的打包工具
webpack核心机制–loader
-
插件机制
-
Loader专注实现资源模块加载
-
Plugin解决其他自动化工作
- e.g.清除dist目录
- e.g.压缩输出代码
- 实现大多前端工程化工作
-
自动清除输出目录的插件
-
- clean-webpack-plugin
命令yarn add clean-webpack-plugin --dev - html-webpack-plugin
- copy-webpack-plugin
- clean-webpack-plugin
插件是通过在声明周期的钩子中挂载函数实现扩展
yarn webpack --watch 打包之后有修改不用重新打包
browser-sync dist --files “**/*” 可以监听变化,自动刷新浏览器
-
集成[自动编译]和[自动刷新浏览器]
-
添加的命令 yarn add webpack-dev-serve --dev
-
运行的命令 yarn webpack-dev-server
-
为了提高效率并没有将打包结果写入磁盘中
-
yarn webpack-dev-server --open 打开浏览器
webpack Dev Server 代理API
devServer:{ ContentBase:'./public', proxy:{ '/api':{ //http://localhost:8080/api/users->https://api.github.com/api/users target:"http://api.github.com", pathRewrite:{ '^/api':'' }, changeOrigin:true } } }
HMR热替换(热拔插)
-
代码修改不会刷新整个页面
-
集成在webpack-dev-server中
-
使用方法:webpack-dev-server --hot 或 在配置文件中添加对应的配置
const webpack=require('webpack')
module.exports={
devServer:{
hot:true
},
plugins:{
new webpack.HotModuleReplacementPlugin()
}
}
然后运行命令:yarn webpack-dev-server --open
其他打包工具
Rollup
与webpack功能相似,更为小巧
ESM打包器,没有其他额外功能,比如:热替换
提供一个充分利用ESM各项特性的高效打包器
快速上手
- 安装Rollup yarn add rollup --dev
- 帮助信息 yarn rollup
- 运行 yarn rollup ./src/index.js --format iife --file dist/bundle.js
配置文件
创建一个文件 rollup.config.js
yarn rollup --config
rollup使用插件
插件是Rollup唯一扩展途径
Parcel
零配置的前端应用打包器
首个版本发布于2017年
完全零配置、构建速度更快
运行 yarn parcel src/index.html
打包 yarn parcel build src/index.html
webpack中可以通过happypack插件实现多线程打包
规范化标准
规范化介绍
-
为什么要有规范化标准
-
- 软件开发需要多人协作
-
- 不同开发者具有不同的编码习惯和喜好
-
- 不同喜好增加项目维护成本
-
- 每个项目或者团队需要明确统一的标准
哪里需要规范化标准
-
- 代码、文档、甚至是提交日志
-
- 开发过程中人为编写的成果物
-
- 代码标准化规范最为重要
实施规范化的方法
-
- 编码前人为的标准约定
-
- 通过工具实现Lint
常见的规范化实现方式
-
- ESLint工具使用
-
- 定制ESLint校验规则
-
- ESLint对TypeScript的支持
-
- ESLint结合自动化工具或webpack
-
- 基于ESLint的衍生工具
-
- stylelint工具的使用
ESLint介绍
- 最为主流的JavaScript Lint工具监测JS代码质量
- ESLint很容易统一开发者的编码风格
- ESLint可以帮助开发者提升编码能力
ESLint安装
- 初始化项目
- 安装ESLint模块为开发依赖
- 通过CLI命令验证安装结果
初始化项目的json文件用于管理项目的npm依赖: npm init --yes
安装: npm install eslint --save-dev
-
查看版本:
-
cd .\node_modules
:cd ..bin\ - .\eslint --version
ESLint快速上手
npx eslint .\01-prepare.js
npx eslint --init
-
ESLint检查步骤
-
- 编写“问题”代码
-
- 使用eslint执行检测
-
- 完成eslint使用配置
npx eslint .\01-prepare.js --fix 自动修正代码问题
配置文件解析
ESLint配置注释
const str1="${name} is a coder"//eslint-disable-line no-template-curly-in-string
ESLint结合自动化工具
- 集成之后,ESLint一定会工作
- 与项目统一,管理更加方便
ESLint结合webpack
现代化项目集成
npm install @vue/cli -g
vue-create syy-vue-app
Babel
ESLint和Standard的配合
Lint on save和Lint and fix on commit
In dedicated config files
最后一个选no
npm run serve
ESLint检查TypeScript
初始化eslint npx eslint --init
在index.ts
function foo(ms:string):void{
console.log(msg);
}
foo('hello typescript~')
npx eslint .\index.ts
Stylelint的认识
- 提供默认的代码检查规则
- 提供CLI工具,快速调用
- 通过插件支持Sass Less PostCSS
- 支持Gulp或Webpack集成
安装 npm install stylelint -D
检测 npx stylelint ./index.css
添加一个配置文件。stylelintrc.js
module.exports={
//extends:"stylelint-config-standard"
//多个
extends:["stylelint-config-standard","stylelint-config-sass-guidelines"]
}
安装共享配置模块
npm install stylelint-config-standard
检测sass 代码
npm install stylelint-config-sass-guidelines -D
Prettier的使用
安装 npm install prettier -D
npx prettier style.css
覆盖原文件 npx prettier style.css --write
npx prettier . --write
Git Hooks工作机制
代码提交至仓库之前未执行lint工作
-
介绍
-
- git hook也称之为git钩子,每个钩子都对应一个任务
-
- 通过shell脚本可以编写钩子任务触发时要具体执行的操作
webpack源码
功能函数说明