跟着老侯玩编程 跟着老侯玩编程
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
首页
  • 基础语法
  • 网络编程
  • 设计模式
  • 基础篇
  • 进阶篇
  • 框架篇
  • Redis
  • Alibaba
  • 课程目录
  • 码农宝典
留言
  • 基础篇

    • 聊聊环境变量
    • 永不过时的HelloWorld
    • 标识符
    • 数据类型
    • 运算符
    • 语句
    • 数组
    • 方法详解
    • 类和对象
    • 类的成员
    • 类的继承
    • 类的形式
    • 封装和多态
    • 接口和Lambda表达式
    • 泛型编程
    • 常用API之函数式接口
    • 常用API
    • 异常机制
    • 多线程
    • 常用API之File类
    • IO流
    • 集合
    • 常用API之Stream流
    • 网络编程
    • 枚举
    • 注解和反射
  • 进阶篇

    • MySQL基础
    • 数据库-JDBC
    • HTML基础
    • CSS基础
    • JavaScript-基础
    • 服务器-Servlet
    • 服务器-Servlet3
    • 动态网页-JSP
    • Ajax
    • 前端项目工程化
      • 前端工程的三个阶段
        • 库 / 框架选型
        • 简单构建优化
        • JS/CSS 模块化开发
      • 组件化开发
      • NPM 包管理器
        • NPM 能干什么
      • NPM 基本使用
        • .npmrc
        • 安装模块
        • 卸载模块
        • 更新模块
      • Webpack 基础
        • 入口 (entry)
        • 输出 (output)
        • loader
        • 插件 (plugins)
        • 案例 -HelloWrold
    • ECMA2015
    • 模块化规范
  • 框架篇

    • 工具-Maven
    • 框架-MyBatis
    • 框架-Spring
    • 框架-SpringMVC
    • 工具-SpringBoot
    • 工具-Nginx
  • Java
  • 进阶篇
舞动的代码
2022-06-23
目录

前端项目工程化

# 前端工程的三个阶段

现在的前端开发倒也并非一无所有,回顾一下曾经经历过或听闻过的项目,为了提升其前端开发效率和运行性能,前端团队的工程建设大致会经历三个阶段:

# 库 / 框架选型

前端工程建设的第一项任务就是根据项目特征进行技术选型。

基本上现在没有人完全从 0 开始做网站,哪怕是政府项目用个 jQuery 都很正常吧,React/Angularjs 等框架横空出世,解放了不少生产力,合理的技术选型可以为项目节省许多工程量这点毋庸置疑。

# 简单构建优化

选型之后基本上就可以开始敲码了,不过光解决开发效率还不够,必须要兼顾运行性能。前端工程进行到第二阶段会选型一种构建工具,对代码进行压缩,校验,之后再以页面为单位进行简单的资源合并。

# JS/CSS 模块化开发

分而治之是软件工程中的重要思想,是复杂系统开发和维护的基石,这点放在前端开发中同样适用。在解决了基本开发效率运行效率问题之后,前端团队开始思考维护效率,模块化是目前前端最流行的分治手段。

JS 模块化方案很多,AMD/CommonJS/UMD/ES6 Module 等,对应的框架和工具也一大堆,CSS 模块化开发基本都是在 less、sass、stylus 等预处理器的 import/mixin 特性支持下实现的。

# 组件化开发

前端是一种技术问题较少、工程问题较多的软件开发领域。

当我们要开发一款完整的 Web 应用时,前端将面临更多的工程问题,比如:

  • 大体量:多功能、多页面、多状态、多系统;

  • 大规模:多人甚至多团队合作开发;

  • 高性能:CDN 部署、缓存控制、文件指纹、缓存复用、请求合并、按需加载、同步 / 异步加载、移动端首屏 CSS 内嵌、HTTP 2.0 服务端资源推送。

这些无疑是一系列严肃的系统工程问题。

分治的确是非常重要的工程优化手段。前端作为一种 GUI 软件,光有 JS/CSS 的模块化还不够,对于 UI 组件的分治也有着同样迫切的需求:

如上图,这是前端组件化开发理念,简单解读一下:

  • 页面上的每个 独立的 可视 / 可交互区域视为一个组件;

  • 每个组件对应一个工程目录,组件所需的各种资源都在这个目录下就近维护;

  • 由于组件具有独立性,因此组件与组件之间可以 自由组合;

  • 页面只不过是组件的容器,负责组合组件形成功能完整的界面;

  • 当不需要某个组件,或者想要替换组件时,可以整个目录删除 / 替换。

其中第二项描述的就近维护原则,它为前端开发提供了很好的分治策略,每个开发者都将清楚的知道,自己所开发维护的功能单元,其代码必然存在于对应的组件目录中,在那个目录下能找到有关这个功能单元的所有内部逻辑,样式也好,JS 也好,页面结构也好,都在那里。

组件化开发具有较高的通用性,无论是前端渲染的单页面应用,还是后端模板渲染的多页面应用,组件化开发的概念都能适用。组件 HTML 部分根据业务选型的不同,可以是静态的 HTML 文件,可以是前端模板,也可以是后端模板:

不同的技术选型决定了不同的组件封装和调用策略。

基于这样的工程理念,我们很容易将系统以独立的组件为单元进行分工划分:

由于系统功能被分治到独立的模块或组件中,粒度比较精细,组织形式松散,开发者之间不会产生开发时序的依赖,大幅提升并行的开发效率,理论上允许随时加入新成员认领组件开发或维护工作,也更容易支持多个团队共同维护一个大型站点的开发。

结合前面提到的模块化开发,整个前端项目可以划分为这么几种开发概念:

名称 说明 举例
JS 模块 独立的算法和数据单元 浏览器环境检测 (detect),网络请求 (ajax),应用配置 (config),DOM 操作 (dom),工具函数 (utils),以及组件里的 JS 单元
CSS 模块 独立的功能性样式单元 栅格系统 (grid),字体图标 (icon-fonts),动画样式 (animate),以及组件里的 CSS 单元
UI 组件 独立的可视 / 可交互功能单元 页头 (header),页尾 (footer),导航栏 (nav),搜索框 (search)
页面 前端这种 GUI 软件的界面状态,是 UI 组件的容器 首页 (index),列表页 (list),用户管理 (user)
应用 整个项目或整个站点被称之为应用,由多个页面组成

以上 5 种开发概念以相对较少的规则组成了前端开发的基本工程结构,基于这些理念,前端开发就成了这个样子:

示意图 描述
整个 Web 应用由页面组成
页面由组件组成
一个组件一个目录,资源就近维护
组件可组合,组件的 JS 可依赖其他 JS 模块,CSS 可依赖其他 CSS 单元

综合上面的描述,对于一般中小规模的项目,大致可以规划出这样的源码目录结构:

如果项目规模较大,涉及多个团队协作,还可以将具有相关业务功能的页面组织在一起,形成一个子系统,进一步将整个站点拆分出多个子系统来分配给不同团队维护

# NPM 包管理器

NPM 全称 node package manger,是 Node 的开放式模块登记和管理系统。

  • 官网:https://www.npmjs.cn/

  • 仓库:https://www.npmjs.com/package/repository

  • 中文参考:https://www.axihe.com/api/npm/api/api.html

# NPM 能干什么

社区的力量,程序员自古以来就有社区文化。加入社区最大的好处之一是,你可以使用别人贡献的代码,你也可以贡献代码给别人用。

社区的意思是:拥有共同职业或兴趣的人们,自发组织在一起,通过分享信息和资源进行合作。虚拟社区的参与者经常会在线讨论相关话题,或访问某些网站。

在 GitHub 还没有兴起的年代,前端是通过网址来共享代码。现在依然没有完全废弃。NPM 最核心的任务就是共享代码

NPM 的思路大概是这样的:

  1. 买个服务器作为代码仓库(registry),在里面放所有需要被共享的代码

  2. 发邮件通知 jQuery、Bootstrap、Underscore 作者使用 npm publish 把代码提交到 registry 上

  3. 社区里的其他人如果想使用这些代码,就把 jquery、bootstrap 和 underscore 写到 package.json 里,执行对应的命令下载这些代码

  4. 下载完的代码出现在 node_modules 目录里,可以随意使用了。这些可以被使用的代码被叫做"包"(package)

# NPM 基本使用

由于新版的 nodejs 已经集成了 npm,所以之前 npm 也一并安装好了。同样可以通过输入 "npm -v" 来测试是否成功安装。

npm init

创建一个 package.json 文件

命令语法

npm init [--force|-f|--yes|-y|--scope]
npm init <@scope> (same as `npx <@scope>/create`)
npm init [<@scope>/]<name> (same as `npx [<@scope>/]create-<name>`)
1
2
3

目录说明

./demo1/
 |-- node_modules  # npm 包存放的文件夹
 |--.npmrc     # npm 配置文件
 |-- package-lock.json  # npm 锁定文件的说明
 |-- package.json   # npm 的 package
1
2
3
4
5

# .npmrc

npm 从命令行,环境变量和 npmrc 文件获取其配置设置

npm config 命令可用于更新和编辑用户和全局 .npmrc 文件的内容

.npmrc 当文件中的行以;或#字符开头时,它们被解释为注释。

存放位置

  • 每个项目的配置文件(/path/to/my/project/.npmrc): 存在于项目根目录下的.npmrc 配置文件

  • 每个用户的配置文件(~/.npmrc):$HOME/.npmrc 存在于用户根目录下

  • 全局配置文件( PREFIX/etc/.npmrc

  • npm 内置配置文件( /path/to/npm/npmrc ):这是一个不可更改的"内置"配置文件,npm 在更新之间保持一致。

; 指定默认的编辑器
editor=C:\Tools\SublimeTextBuild3207x64\sublime_text.exe
; 模块库
registry=https://registry.npm.taobao.org
; 模块安装地址
prefix=C:\nodejs-moudules\moudules
; 临时文件地址
tmp=C:\nodejs-moudules\tmp
; 缓存地址
cache=C:\nodejs-moudules\npm_cache
1
2
3
4
5
6
7
8
9
10

npm config

该命令可用于查看、编辑用户和全局 npmrc 文件的内容。

命令语法

npm config set <key> <value> [-g|--global]
npm config get <key>
npm config delete <key>
npm config list [-l] [--json]
npm config edit
npm get <key>
npm set <key> <value> [-g|--global]
1
2
3
4
5
6
7

# 安装模块

命令语法

npm install (with no args, in package dir)
npm install [<@scope>/]<name>
npm install [<@scope>/]<name>@<tag>
npm install [<@scope>/]<name>@<version>
npm install [<@scope>/]<name>@<version range>
npm install <git-host>:<git-user>/<repo-name>
npm install <git repo url>
npm install <tarball file>
npm install <tarball url>
npm install <folder>
1
2
3
4
5
6
7
8
9
10

默认将所有指定的软件包保存到其中。此外,您可以使用一些其他标志来控制在何处以及如何保存它们:

  • -D, –save-dev:包将出现在您的中 devDependencies。

局部安装

  • 将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。

  • 可以通过 require() 来引入本地安装的包。

全局安装

  • 将安装包放在 /usr/local 下或者你 node 的安装目录。

  • 可以直接在命令行里使用。

 npm install express -g
1

# 卸载模块

我们可以使用以下命令来卸载 Node.js 模块。

npm uninstall express

npm cache clean
1
2
3

# 更新模块

我们可以使用以下命令更新模块:

npm update express
1

# Webpack 基础

Webpack 是基于 nodejs 实现的, Node.js 是前端工程化的重要支柱之一,所以想使用 Webpack 构建项目,首先需要做的是理清楚 NPM 、NodeJS 以及 Webpack 他们之间的关系

  • NodeJS 是 JavaScript 编写服务器端代码的一个运行环境,类似于 Java 的 JDK

  • NPM 是 NodeJS 的一个功能模块,主要用于安装依赖

  • Webpack 是基于 NodeJS 实现的一个软件,所以它里面所有功能 (loader、plugins) 都是通过 NPM 进行安装的

  • NPM 的服务器在国外,因为防火墙的原因,所以下载东西速度会很慢,CNPM 是淘宝提供的 NPM 国内版本,服务器在国内

    yarn 和 npm 一样,也是基于 NodeJS 实现的一个依赖管理工具,因为内部机制不同所以只是下载速度和信息提示相对 npm 来说更友好一点,个人不建议使用 yarn

本质上,Webpack 是一个现代 JavaScript 应用程序的静态模块打包器 (module bundler)。当 Webpack 处理应用程序时,它会递归地构建一个依赖关系图 (dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。

从 Webpack v4.0.0 开始,可以不用引入一个配置文件。然而,Webpack 仍然还是高度可配置的。在开始前你需要先理解四个核心概念

# 入口 (entry)

入口起点 (entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,Webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。

# 输出 (output)

output 属性告诉 Webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。你可以通过在配置中指定一个 output 字段,来配置这些处理过程

# loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。

# 插件 (plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项 (option) 自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

参考地址列表:

  • npm:https://www.npmjs.com.cn/getting-started/what-is-npm

  • cnpm:https://npm.taobao.org

  • yarn:https://yarn.bootcss.com

  • webpack:https://www.webpackjs.com

  • NodeJS:http://nodejs.cn

# 案例 -HelloWrold

官方文档:https://www.webpackjs.com/guides

# 创建项目
npm init -y
# 安装 webpack
npm install webpack --save-dev
npm install webpack webpack-cli --save-dev

1
2
3
4
5
6

完整的 package.json 内容如下:

{
  "name": "demo1",
  "version": "1.0.0",
  "description": "",
  "scripts": {
   "build": " webpack --config webpack.config.js --progress  --colors ",
    "dev": "webpack-dev-server --inline --colors --progress"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.2",
    "webpack-dev-server": "^3.3.1"
  },
  "dependencies": {
    "jquery": "^3.4.1"
  }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

核心内容说明:

  • name:用于标明项目名称,该属性必须存在,同时要求名称中不能出现大写字母

  • version:用于标明项目的版本号,该属性必须存在,版本号一般有三部分组成:主版本。次版本。bug 修复版本

  • scripts:我们可以借助 npm 执行一些复杂的命令,而为了避免每次都输入这些复杂的命令,可以借助该属性将这些复杂的命令做成小脚本,运行其中某个脚本的命令如下:npm run 脚本名称 例如:npm run dev

  • devDependencies:用于记录在开发环境中依赖的版本和名称,使用npm i jquery --save-dev就可以把依赖信息写入。在新版本的 npm 中已经可以使用 -D 来代替 --save-dev,完整的例子:npm i jquery -D

  • Dependencies:用于记录在生产环境中依赖的版本和名称。使用npm i jquery --save就可以把依赖信息写入

现在我们将创建以下目录结构、文件和内容:

webpack-demo
    |- package.json
    |- index.html
    |- /src
        |- index.js
1
2
3
4
5

src/index.js


function component() {
  var element = document.createElement('div');

  // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
  element.innerHTML = _.join(['Hello', 'webpack'], ' ');

  return element;
}

document.body.appendChild(component());

1
2
3
4
5
6
7
8
9
10
11
12

index.html

<!doctype html>
<html>
  <head>
    <title>起步</title>
    <script src="https://unpkg.com/lodash@4.16.6"></script>
  </head>
  <body>
    <script src="./src/index.js"></script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10

使用这种方式去管理 JavaScript 项目会有一些问题:

  • 无法立即体现,脚本的执行依赖于外部扩展库 (external library)。

  • 如果依赖不存在,或者引入顺序错误,应用程序将无法正常运行。

  • 如果依赖被引入但是并没有使用,浏览器将被迫下载无用代码。

调整目录结构,让 webpack 来管理这些脚本

  webpack-demo
  |- package.json
  |- /dist
    |- index.html
  |- /src
    |- index.js

1
2
3
4
5
6
7
# 安装 lodash

npm install --save lodash
1
2
3

src/index.js

import _ from 'lodash';
function component() {
    var element = document.createElement('div');

    // Lodash(目前通过一个 script 脚本引入)对于执行这一行是必需的
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');

    return element;
}

document.body.appendChild(component());

1
2
3
4
5
6
7
8
9
10
11
12

dist/index.html

<!doctype html>
<html>

<head>
    <title>起步</title>
</head>

<body>
    <script src="main.js"></script>
</body>

</html>

1
2
3
4
5
6
7
8
9
10
11
12
13

执行 npx webpack,会将我们的脚本作为入口起点,然后 输出 为 main.js

Ajax
ECMA2015

← Ajax ECMA2015→

Theme by Vdoing | Copyright © 2013-2023 冀ICP备16006233号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×