前端领域框架百花齐放, 各种优秀框架出现 (react,vue,ag) 等等框架. 为了方便开发者快速开发, 开发对应的 cli 脚手架, 来提高产出. 然而初中级的前端工程师对项目里的 webpack 封装和配置了解的不清楚, 就容易导致出问题不知如何解决, 甚至不会通过 webpack 去扩展新功能, 对 webpack + vue 项目究竟是怎样搭建起来的感到一脸困惑, 下面我们就来解决这个问题, 揭开 webpack 构建 vue 的面纱.
什么是 webpack ?
酷炫动画的页面, 高度复杂的页面功能, 页面内容支持预加载(图片, 骨架屏) , 这些高要求导致了项目的增加更多的代码. 代码的增多, 使得由来代码需要被组织的需求, 由此产生了模块化.
模块化的发展历程
传统的 <script> 标签, 一个标签加载一个 JS 文件. 缺点就是全局变量太多, 容易出现冲突, 另外依赖顺序很重要, 太多 JS 不好管理 . 后面出现了 node.JS, 有了 CommonJS 规范(同步的 require 请求), 即一个模块是一个文件, 想用谁直接 require 谁, 想被谁用, 就 module.exports 导出去.
虽然服务端使用起来方便, 但是浏览器通过网络请求获取文件是异步的, 所以出现了矛盾. 为了解决 CommonJS 规范的缺陷, AMD 规范 (异步的 require 请求) 出现了, 满足异步的网络请求, 可以并行加载多个文件 ES6 modules,ES6 中自带对应的模块语法 input/exports, 静态分析容易. 但浏览器支持度不够, 模块较少. 为此 webpack 出现解决上述遇到的问题.
模块化的解决方案 - webpack
Webpack 是一个现代 JavaScript 应用程序的静态模块打包器 (module bundler). 在 webpack 中所有的文件都将被当做模块使用, 当 webpack 处理应用程序时, 它会递归地构建一个依赖关系图(dependency graph), 其中包含应用程序需要的每个模块, 然后将所有这些模块打包成一个或多个 bundle . 举例: 把你的项目当做一个整体, 通过一个给定的主文件(如: mian.JS), webpack 将这个文件开始找到你项目的所以依赖文件, 使用 loaders 或者是 plugins 去处理它们, 最后打包成一个(或者多个) 浏览器可以识别的 JavaScript 文件.
webpack 的优缺点
先来看看 webpack 的 3 个优点:
模块化打包: 将 CSS,JS,ts,Sass 等统一转换为浏览器可以识别的模式, 并按需 (压缩或不压缩) 打包.
webpack-plugin:webpack-plugin 是用来扩展 webpack 功能的插件, 用来扩展 webpack 功能, 并在整个构建过程中生效, 执行相关任务.
按需加载: 代码中不需要的模块不被打进包里, 或者按需加载. 这是传统的流程构建工具, 如 Gulp,Grunt 等所没办法实现的.
也不能忽视它的下列缺点:
传统技术开发的复杂项目不适用: 一些比如 jQuery,RequireJS,SeaJS 等脚本模块化开发的复杂项目项目, 由于打包需求不稳定, webpack 维护成本极高.
侵入性较强: 使用 webpack 的项目, 某些高级语法特性需要依赖独特语法实现, 在一定程度上属于面向 webpack 开发, 需要一定的学习成本.
兼容性问题: webpack 一向是面对最新标准, 自身的很多特性需要 polyfill 才能向下兼容, 甚至有些特性最新浏览器还没有原生兼容, 在做开发时候需要注意.
webpack 的构建流程
Webpack 的构建流程是一种事件流机制. 整个构建流程可以看成是一个流水线, 每个环节负责单一的任务, 处理完将进入下一个环节.
Webpack 会在每个环节上发布事件, 供内置的和自定义的插件有机会干预 Webpack 的构建过程, 控制 Webpack 的构建结果
初始化参数: 从配置文件和 Shell 语句中读取与合并参数, 得出最终的参数.
开始编译: 用上一步得到的参数初始化 Compiler 对象, 加载所有配置的插件, 执行对象的 run 方法开始执行编译. 确定入口: 根据配置中的 entry 找出所有的入口文件.
编译模块: 从入口文件出发, 调用所有配置的 Loader 对模块进行翻译, 再找出该模块依赖的模块, 再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理.
完成模块编译: 在经过第 4 步使用 Loader 翻译完所有模块后, 得到了每个模块被翻译后的最终内容以及它们之间的依赖关系.
输出资源: 根据入口和模块之间的依赖关系, 组装成一个个包含多个模块的 Chunk, 再把每个 Chunk 转换成一个单独的文件加入到输出列表, 这步是可以修改输出内容的最后机会.
输出完成: 在确定好输出内容后, 根据配置确定输出的路径和文件名, 把文件内容写入到文件系统.
熟悉了 webpack 基本的构建流程那下面我们就进行实践操作构建 vue 项目
webpack 构建 vue 项目
安装 webpack
使用版本: webpack5.x
新建 webpack-vue 项目, 进入项目根目录, 创建默认的 package.JSON
安装 webpack 和 webpack-cli:
webpack - 模块打包库
webpack-cli - 命令行工具
新建 src/main.JS, 里面随便写点 console.log('hello,webpack-vue')
result:
基础配置
新建一个 build 文件夹, 新建一个 vue.config.JS
Entry
入口文件, webpack 会首先从这里开始编译
Output
定义了打包后输出的位置, 以及对应的文件名.[name]是一个占位符
result:
plugins
当我们构建项目时生成了 main.JS 之后, 需要一个 html 页面去展示, 然后再 HTML 引入 JavaScript, 当我们配置打包输出的 bundle 文件都配置了随机 hash 值, 每次手动插入和下一次更新就特麻烦, 最好方法是每次构建完成后自动将新的 bundle 打包到 HTML 中并删除上一次旧的 bunble, 所以我们需要 HTML-webpack-plugin ,clean-webpack-plugin 插件来帮我们自动引入和删除历史 bundle 文件
根目录新建一个 public/index.HTML 默认模板
配置 vue.config.JS
result:
loaders
webpack 识别 CSS,Sass 安装 loader, 并将解析后的 CSS 插入到 index.HTML 里面的 style
result:
识别压缩图片, 字体
webpack 识别图片, 视频, 字体, 减少图片字体等打包的大小. 我们可以使用 url-loader 将少于指定大小的文件转换为 base64, 使用 file-loader 将大于指定大小的文件移动到指定的位置
Babel
Babel 是一个 JavaScript 编译器, 能将 ES6 + 代码转为 ES5 代码, 让你使用最新的语言特性而不用担心兼容性问题,
在 Babel 执行编译的过程中, 会从项目根目录下的配置文件读取配置. 在根目录下创建 Babel 的配置文件 .babelrc
兼容 vue
- vue-loader
- vue-template-compiler
- vue-style-loader
src 文件夹内新建一个 App.vue, 内容自定义
热更新 HMR
配置 package.JSON
- package.JSON:"dev":"webpack serve --config build/vue.config.js"
- result:
来源: https://segmentfault.com/a/1190000040340016