前端需要理解的工程化知识

前端需要理解的工程化知识_第1张图片

1 Git

前端需要理解的工程化知识_第2张图片

1.1 Git 常见工作流程

 Git 有4个区域:工作区(workspace)、index(暂存区)、repository(本地仓库)和remote(远程仓库),而工作区就是指对文件发生更改的地方,更改通过git add 存入暂存区,然后由git commit 提交至本地仓库,最后push推送到远程仓库。

工作目录包括.git 子目录(包含仓库所有相关的 Git 修订历史记录)、工作树,或签出的项目文件的副本。

裸存储库只包含版本控制信息而没有工作文件(工作树)而且.git 子目录中的所有内容存在于主目录

完成提交(commit)前,称为“staging area”或“index”。此区域可对其进行格式化和审查。git 会在提交之前触发 pre-commit hook,使用pre-commit hook相关的脚行对提交到存储库中的更改执行完整性检查等,不满足可以阻止提交操作。

常见工作场景:

  1. 初始化本地仓库:

    前端需要理解的工程化知识_第3张图片

  2. 创建本地分支并推送关联远程:

    前端需要理解的工程化知识_第4张图片

  3. 查看分支:

    前端需要理解的工程化知识_第5张图片

  4. 合并分支:

    前端需要理解的工程化知识_第6张图片

  5. 删除分支:

    前端需要理解的工程化知识_第7张图片

  6. 标签管理:

    前端需要理解的工程化知识_第8张图片

  7. push变更代码的流程:

    前端需要理解的工程化知识_第9张图片

  8. 开发新feature功能:新建一个feature分支,并关联远程分支,然后合并到开发分支(如果存在),确定没问题再MR合并到master分支。

  9. bug修复:新建一个bugfix分支,并关联远程分支,然后合并到开发分支(如果存在),确定没问题再MR合并到master分支;

git stash:将工作目录(修改后的跟踪文件和暂存的更改)保存在一堆未完成的更改中并且可以随时重新应用这些更改。

1.2 git pull 和 git fetch

git pull :从中央存储库中提取特定分支的新更改或提交,并更新本地存储库中的目标分支

git fetch :相同的目的,但工作方式略不同。 git fetch 从所需的分支中提取所有新提交存储在本地存储库中的新分支中。若要在目标分支中反映这些更改,必须在 git fetch 之后执行git merge。只有在对目标分支和获取的分支进行合并后才会更新目标分支。

git pull = git fetch + git merge

前端需要理解的工程化知识_第10张图片

1.4 Git 和 SVN

Git是分布式版本控制工具,可本地系统克隆远端存储库,支持离线提交,基于C语言,push/pull很快,通过commit实现共享。不依赖于中央服务器来存储项目文件的所有版本。

SVN是集中版本控制工具,存储在服务器,仅支持在线提交,push/pull较慢,不支持共享。

1.5 git merge 和 git rebase

两者都是用于分支合并,关键在 commit 记录的处理上不同:

·git merge 会新建一个新的 commit 对象,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会保留之前每个分支的 commit 历史。

·git rebase 会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,然后将这个 commit 记录添加到目标分支的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记录了。而且git rebase 后git push需要添加 --force 进行强制推送。

1.6 git config

core.ignorecase:是否忽略大小写,默认情况下是false,除了git-clone和git-init会在创建仓库时探测并适当地设置core.ignoreCase为true。如果为true,这个选项可以启用各种变通方法,使Git在不区分大小写的文件系统(如FAT)上更好地工作。

2 webpack

Webpack核心能力:1. 打包压缩(js混淆防止源码被利用),减少网络传输;2. 文件指纹,合理利用http缓存;3. 开发服务器,热更新,改善开发体验。

Webpack的好处:1. 可以使用任意模块化标准,无须担心兼容性问题。2. 可以将非JS视为模块,使得对css、图片等资源进行更细粒度的控制。3. 前端开发也能使用npm,wepack不会运行源代码,而是作为依赖,最终合并打包。4. 非常适合开发单页应用。

webpack会非常暴力的将public目录中除页面模板(index.html)的文件复制到打包结果中。

除JS和css模块外,其他模块被视为资源模块。webpack是无法识别JS中直接书写的路径字符串的,只有通过模块化的方式导入资源,资源才会被视为模块,webpack才能将该资源的原始路径转换为打包结果的真实路径。

2.1 核心概念

2.1.1 bundle,chunk,module

bundle:是由webpack打包出来的可在浏览器直接运行的⽂件;chunk是无法在打包结果中看到的,打包结果中看到的是bundle。

chunk:代码块,⼀个chunk由多个模块组合⽽成,⽤于代码的合并和分割;简单来说,它表示通过某个入口模块找到的所有依赖的统称。每个chunk都至少有两个属性:

  1. name:默认是main;
  2. id:开发环境和name相同,生产环境是一个数字,从0开始。

module:是开发中的单个模块,在webpack的世界,⼀切皆模块,⼀个模块对应⼀个⽂件,webpack会从配置的 entry中递归开始找出所有依赖的模块。

module 就是没有被编译之前的代码,通过 webpack 的根据文件引用关系生成 chunk 文件,webpack 处理好 chunk 文件后,生成运行在浏览器中的代码 bundle。

2.1.2 构建流程

前端需要理解的工程化知识_第11张图片

前端需要理解的工程化知识_第12张图片

Webpack 的运⾏(编译、构建或打包)流程是⼀个串⾏的过程,从启动到结束会依次执⾏以下流程:

  1. 初始化参数:从配置⽂件和 Shell 语句(CLI)中读取与合并参数并与默认配置融合,得出最终的参数;依托第三方库yargs完成。
  2. 开始编译:⽤上⼀步得到的参数初始化 Compiler 对象,加载所有配置的插件,执⾏对象的 run ⽅法开始执⾏编译;
  3. 确定⼊⼝:根据配置中的 entry 找出所有的⼊⼝⽂件;
  4. 编译模块:从⼊⼝⽂件出发,调⽤所有配置的 Loader 对模块进⾏翻译(语法分析转换为AST),再找出该模块依赖的模块进行记录,再递归本步骤直到所有⼊⼝依赖的⽂件都经过了本步骤的处理;
  5. 完成模块编译:在经过第4步使⽤ Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
  6. 输出资源:根据⼊⼝和模块之间的依赖关系,组装成⼀个个包含多个模块的 Chunk,再把每个 Chunk 转换成⼀个单独的⽂件加⼊到输出列表,这步是可以修改输出内容的最后机会;
  7. 输出完成:在确定好输出内容后,根据配置确定输出的路径和⽂件名,把⽂件内容写⼊到⽂件系统。

在以上过程中,Webpack 会在特定的时间点⼴播出特定的事件,插件在监听到感兴趣的事件后会执⾏特定的逻辑,并且插件可以调⽤ Webpack 提供的 API 改变 Webpack 的运⾏结果。

target配置选项是构建目标,指定构建出对应运行环境的代码。默认值为 "browserslist",如果没有找到 browserslist 的配置,则默认为 "web"。虽然 webpack 不支持 向 target 属性传入多个字符串,但是可以通过设置两个独立配置(module.exports = [serverConfig, clientConfig];),来对 library 进行多套构建。

前端需要理解的工程化知识_第13张图片

2.1.3 mode 模式

提供 mode 配置选项,告知 webpack 使用相应模式的内置优化。Webpack4+支持,取值有 'none' | 'development' | 'production',默认值是 'production'。

前端需要理解的工程化知识_第14张图片

(1)development

  1. 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。
  2. 启用 NamedChunksPlugin 和 NamedModulesPlugin 为所有的module(源文件)和chunk(构建输出的文件)定义一个名字。方便于浏览器调试;可以快速地对增加的内容进行编译;提供了更精确、更有用的运行时错误提示机制。

(2)production

  1. 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。
  2. 启用插件(最后一个为非内置插件):
    • FlagDependencyUsagePlugin:检测并标记模块之间的从属关系
    • FlagIncludeChunksPlugin:可以让 Webpack 根据模块间的关系依赖图中,将所有的模块连接成一个模块
    • ModuleConcatenationPlugin:告诉 Webapck 去清除一个大的模块文件中的未使用的代码,这个大的文件模块可以是自定义的,也可以是第三方的(注意:一定要 package.json 文件中添加 "sideEffects": false)
    • NoEmitOnErrorsPlugin
    • OccurrenceOrderPlugin
    • SideEffectsFlagPlugin:告知 Webapck 各个模块间的先后顺序,这样可以实现最优的构建输出
    • TerserPlugin:替代 uglifyjs-webpack-plugin 插件。它的作用依然是对构建输出的代码进行压缩

(3)none:不使用任何默认优化选项,即启动 Webpack 打包时关闭默认的内置插件。

前端需要理解的工程化知识_第15张图片

2.1.4 entry 入口 

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

Webpack 寻找相对路径的文件时(解析入口点(entry point)和加载器(loader))会以 context 配置选项为根目录,context 配置选项必须是绝对路径字符串。默认使用 Node.js 进程的当前工作目录,但是推荐在配置中传入一个值,使得配置独立于 CWD(current working directory, 当前工作目录)。

前端需要理解的工程化知识_第16张图片

Webpack提供entry 配置选项,来指定一个(或多个)不同的入口起点,默认值是 ./src/index.js。

单入口语法:string | string[],是多入口对象语法中只有一个main-chunk的简写。entry 设置为string[],在作为库的时候即和output.library一起使用时只有数组中最后一个模块会暴露。

前端需要理解的工程化知识_第17张图片

Webpack 配置的可扩展是指配置可重用,并且可以与其他配置组合使用,使得可以将关注点从环境(environment)、构建目标(build target)、运行时(runtime)中分离。然后使用专门的工具(如 webpack-merge)将它们合并起来。

多入口对象语法:entry: { string | [string] } | {},entry 是一个 object,对象中每个属性对应一个Chunk,属性名key即chunk名,属性值value可以是string | string[] | {},描述每个入口的对象有如下属性

  1. dependOn:当前入口所依赖的入口,它们必须在该入口被加载前被加载。使用 dependOn 选项可以与另一个入口 chunk 共享模块(相当于将依赖的入口从当前入口剥离)。
  2. filename:指定要输出的文件名称。
  3. import:启动时需加载的模块。
  4. library:指定 library 选项,为当前 entry 构建一个 library。
  5. runtime:运行时 chunk 的名字。如果设置了,就会创建一个新的运行时 chunk。
  6. publicPath:当该入口的输出文件在浏览器中被引用时,为它们指定一个公共 URL 地址。

确保runtime 和 dependOn 不应在同一个入口上同时使用,确保dependOn 不能是循环引用的,确保 runtime 不能指向已存在的入口名称,否则均会抛出错误。

 前端需要理解的工程化知识_第18张图片

分离 app(应用程序) 和 vendor(第三方库) 入口的场景,webpack4开始,不推荐为 vendor 或其他不是执行起点创建 entry,而是应该使用 optimization.splitChunks 选项,将 vendor 和 app模块分开,并为其创建一个单独的文件。在多页面应用程序中,server会拉取一个新的 HTML 文档到客户端。页面重新加载此新文档,并且资源被重新下载。借助optimization.splitChunks 为页面间共享的应用程序代码创建 bundle,并对多个入口起点之间的大量代码/模块进行复用。根据经验,每个 HTML 文档只使用一个入口起点。

动态入口语法:entry设置为一个函数,那么它将会在每次 make 事件中被调用。make 事件在 Webpack 启动和每当监听文件变化时都会触发。动态入口使得可以从外部来源(远程服务器,文件系统内容或者数据库)获取真正的入口。

前端需要理解的工程化知识_第19张图片

2.1.5 output 输出

output 配置选项指定webpack 对「bundle、asset 和其他所打包或使用 webpack 载入的任何内容」如何进行输出和输出位置。只能指定一个 output 配置。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

在 webpack 配置中,output 配置选项的最低要求是,包括output.filename的一个对象。

output.filename

如果webpack配置会生成多于一个 "chunk"(例如,使用多个入口起点或使用 CommonsChunkPlugin 插件),则在output.filename上应该使用占位符(substitutions) 来确保每个文件具有唯一的名称。占位符可以是以下一个或多个组合:

  1. [name]:chunk 名称。
  2. [id]:内部chunk id,从0自增。
  3. [fullhash]:整个编译过程(compilation)的 hash,webpack4是[hash](已弃用)。
  4. [chunkhash]:每一个入口(entry)的hash。
  5. [contnethash]:每一个模块的hash。

因为 ExtractTextWebpackPlugin 提取出来的内容是代码内容本身,而不是由一组模块组成的 Chunk,所以ExtractTextWebpackPlugin 插件使用 contenthash 而不是 chunkhash 来代表哈希值。

hash的长度可以使用 [chunkhash:16](默认为 20)来指定,或者通过指定 output.hashDigestLength 在全局配置长度

也可以使用函数:

前端需要理解的工程化知识_第20张图片

output.pathinfo

类型是boolean | 'verbose',用于告知 webpack 在 bundle 中引入「所包含模块信息」的相关注释。此选项在 development 模式时的默认值为 true,而在 production 模式时的默认值为 false。当值为 'verbose' 时,会显示更多信息,如 export以及运行时依赖。生产环境(production)下,不应该使用true 或  'verbose'。

output.publicPath

用于指定在浏览器中所引用的「此输出目录对应的公开 URL」,相对 URL(relative URL) 会被相对于 HTML 页面(或  标签)解析。相对于服务的 URL(Server-relative URL)、相对于协议的 URL(protocol-relative URL) 或绝对 URL(absolute URL) 也可能用到,比如托管在CDN的资源。

该选项的值是以 runtime(运行时) 或 loader(载入时) 所创建的每个 URL 的前缀。因此大多数情况,该选项的值以 / 结尾。

对于按需加载(on-demand-load)或加载外部资源(external resources)(如图片、文件等)来说,output.publicPath 是很重要的选项。如果指定错误的值,会导致404错误。

output.chunkFilename

只用于配置非初始(non-initial)chunk 文件,即在运行时生成的chunk的名称。取值和output.filename类似。常见场景包括:

  1. 使用 CommonsChunkPlugin,用于创建一个单独的文件中,由多个入口点之间共享的公共模块。不过从 Webpack v4+ 开始,CommonsChunkPlugin 已被删除,转而使用 optimization.splitChunks。
  2. 使用 import('path/to/module') 动态加载的模块等。
output.crossOriginLoading

按需加载是通过JSONP实现的。JSONP 的原理是动态地向 HTML 中插入一个 

你可能感兴趣的:(前端,面试,前端,npm,工程化)