1. webpack是现代Javascript应用程序的静态木块打包工具,当webpack处理应用程序时,会在内部构建一个依赖图,此依赖图会映射项目所需的每个模块,并生成一个或多个bundle包,weback本身基于node.js开发的
  2. - grunt
  3. - gulp
  4. - fis
  5. - webpack
  6. - snowpack
  7. - ...
  8. 官网:https://webpack.docschina.org/

为什么使用webpack

  • 合并压缩文件
  • 代码转换: TypeScript 编译成Javascript、Less/Scss编译成CSS,ES6/7编译成ES5、虚拟DOM编译成真实的DOM等等
  • 文件优化:压缩JS、CSS、HTML代码、压缩合并图片、图片BASE64等
  • 代码分割:提取多个页面的公共代码,提取首屏不需要执行部分代码等
  • 模块合并:采用模块化的项目里会有很多个模块和文件、需要构建功能把模块分类合并成一个文件
  • 自动刷新:监听本地源代码的变化、自动重新构建、刷新浏览器
  • 代码校验:ESlint代码规范校验和检测、单元测试等
  • 自动发布:自动构建出线上发布代码并传输给发布系统

1、前端开发的模块化进化史

JavaScript本身是弱化命名空间概念的,只有全局作用域和函数私有作用域(ES6新增块级作用域),而模块化开发,从某种意义上说,是强化了命名空间的概念!

  • 有利用于代码分离、解藕,和复用
  • 团队并行开发
  • 避免命名冲突
  • 互相引用,按需加载

模块化的发展史:

  • 单例设计模式
  • AMD
  • CMD
  • CommonJS
  • ES6 Module (JS官方标准定义方式)

1、单例设计模式

  1. let xxxModule = (function(){
  2. function fn(){
  3. // ...
  4. }
  5. return {
  6. init(){
  7. // ...
  8. }
  9. }
  10. })();
  11. xxxModule.init();

2、AMD require.js

官网:https://requirejs.org
AMD思想:依赖前置, 定义一个新的模块之前,需要把依赖的模块全部设定好

  1. npm i requirejs -S

image.png
image.png
main.js

  1. // 全局配置
  2. var requirejs = require('requirejs');
  3. requirejs.config({
  4. baseUrl:"./lib",
  5. })
  6. requirejs(['moduleB','moduleA'],function (moduleB,moduleA) {
  7. console.log(moduleB.average(10,20,30,40,50))
  8. });

moduleA.js

  1. define(function (){
  2. return {
  3. sum(...args) {
  4. console.log(args,'args>>>')
  5. return args.reduce((total,item) => {
  6. return total + item
  7. })
  8. }
  9. }
  10. })

moduleB.js

  1. define(['moduleA'], function (moduleA){
  2. console.log(moduleA)
  3. return {
  4. average(...args) {
  5. args.sort((a,b)=> a-b);
  6. args.pop();
  7. args.shift();
  8. return moduleA.sum(...args) / args.length;
  9. }
  10. }
  11. })

AMD 思想特点: 依赖前置 定义一个新的模块之前,需要把依赖的模块全部设定好
缺点:事前不知道依赖哪个模块

3、CDM —— sea.js

http://seajs.org/
CMD参考了CommonJS ,将模块导入导出从服务端搬到客户端

  1. define(function(require,exports,module){
  2. // 通过 require 引入依赖
  3. var $ = require('jquery');
  4. let spinning = require('./spinning');
  5. // 通过 module.exports 提供接口
  6. module.exports = {
  7. init(){}
  8. }
  9. })

CMD 相对于AMD 更灵活,不用考虑依赖前置
https://my.oschina.net/blueskyer/blog/176544

4、 CommonJS 规范

在CommonJS模块中,如果require了一个模块,相当于执行了该文件中的代码并执行了该代码并最终获取到了这个模块的输出 module exports 对象的一份拷贝,并且重复引用模块并不会重复执行,再次获取模块只会获取之前获取的模块的拷贝

  • module.exports
  • require

image.png
a.js

  1. function sum(a,b){
  2. console.log(a+b)
  3. }
  4. module.exports = {
  5. sum
  6. }

b.js

  1. let x = 10, y = 20;
  2. let A = require('./a')
  3. // 第一次require模块,会把模块中的代码执行,创建变量A,把模块中的module.exports导出结果拷贝一份给变量
  4. A.sum(x,y)
  5. A = require('./a')
  6. // 第二次require模块,内部默认会看一下之前有没有导入过,如果导入过不会再把A代码重新执行,而是直接获取上一次拷贝的信息

ES6 Module 模块规范

https://es6.runyifeng.com/#docs/module
ES6Module是JS新增的模块导入导出规范,不同于AMD和CMD,它是静态编译的

  • 动态编译,代码执行到具体位置才会进行模块的导入导出
  • 静态编译,代码还没有执行,就按照依赖的关系把模块导入导出和编译好了

  • 模块导入必须放到代码执行前面

  • 浏览器不能直接识别,需要进行编译才可以 (webpack)

a.js

  1. export function sum(x,y) {
  2. return x + y
  3. }
  4. export let n = 10;
  5. export default function c(){} // 默认导出 只导出一个 import 一个

b.js

  1. import { sum,n } from './A'
  2. // => import * as A from './A'
  3. // A.sum()
  4. // A.n

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>Document</title>
  7. </head>
  8. <body>
  9. <script type="module">
  10. import * as A from './a.js';
  11. console.log(A)
  12. </script>
  13. <!-- <script type="module" src="./b.js"></script> -->
  14. </body>
  15. </html>

2、 NPM 操作指南

  1. // 安装模块
  2. npm install xxx
  3. npm i less -g
  4. npm i less@xx.xx
  5. npm i less@latest
  6. npm uninstall less -g
  7. npm root -g 查看全局地址
  8. npm view less versions > less.version.json
  9. // -x 压缩
  10. lessc less/1.less css/1.min.css -x

全局安装特点
1、所有项目都能使用
2、一般可以使用命令操作
3、容易版本冲突
4、安装在全局的模块不能基于CommonJS等模块规范在代码中导入模块,实现对应的效果

安装到本地
1、安装在全局的模块可以基于CommonJS等模块规范在代码中导入模块,实现对应的效果
2、默认是不能使用命令了

真实项目中一般既安装到本地又全局

  • npx 5.x 以上 只要本地有这个文件 并且可以执行
  • 本地可执行脚本文件 npm init -y 在script中配置命令

hundLess.js

  1. let less = require('less'),
  2. fs = require('fs');
  3. less.render(fs.readFileSync('./less/1.less','utf-8'),(err,result) => {
  4. fs.writeFileSync('./css/1.css', result.css, 'utf-8')
  5. })

优化速度

  • npm
  • yarn
  • cnpm

https://npmjs.com 国外
安装cnpm 淘宝镜像源
yarn 从源和内部机制上都比npm好一些
yarn add yarn remove
npm i nrm -g
nrm ls
切源工具
npm config get registry 查看npm源
nrm use xxx 切换源

npm 的常规操作

npm init -y
1、记录了当前需要开发和生产依赖项的模块清淡
2、可以配置可执行的脚本文件
3、配置其他信息供node或者webpack编译的时候使用

less开发需要 jquery开发生产都需要,
dependencies 生产依赖 npm i xxx 或者 —save 或者 -S
devDependencies 开发依赖 npm i xxx -D 或者—save-dev

npm i 安装所有依赖
npm i —production 安装生产依赖

npm 进阶

如何自己安装模块
自己写插件
上传npm打包 上传等