目录
0.为什么要写这个文章?
1.Webpack
1.1.概念
1.2.基本概念
1.2.1.入口(entry)
1.2.2.输出(output)
1.2.3.loader
1.2.4.插件(plugin)
1.2.5.模式(mode)
1.2.6.浏览器兼容性(browser compatibility)
1.2.7.环境(environment)
1.3.配置(Configuration)
1.4.模块解析(Module Resolution)
1.4.1.webpack 中的解析规则
1.5.Module Federation
1.5.1.动机
1.5.2.底层概念
1.5.3.底层概念:重载(Overriding)
1.5.4.高级概念
1.6.依赖图(dependency graph)
1.7.target属性
1.8.manifest文件
1.9.模块热替换
2.Vue CLI
2.1.介绍
2.2.安装
2.3.基础
2.3.1.快速原型开发
2.3.2.创建一个项目
2.3.3.插件
2.3.4.Preset
2.3.5.CLI服务
2.4.开发
2.4.1.浏览器兼容性
2.4.2.HTML和静态资源
2.4.3.CSS 相关
2.4.4.模式和环境变量
2.4.5.构建目标
一方面,把官网内容记录下来,既方便查找,也方便浏览,另外一方面,我这里都是摘抄自官方,还没有添加自己的理解,等后面有机会遇到这方面问题的时候,我会删除官方的记录,然后全部变成个人心得;
官网:https://webpack.docschina.org/concepts/
按照官网介绍,Webpack本质上是一个“静态模块打包工具”、“内部构建一个依赖图”、“并生成一个或多个 bundle”。
指示webpack应该使用哪个模块,来作为构建其内部依赖图(dependency graph)的开始。
单个入口(简写)语法:entry: string | [string]
对象语法:entry: {
用于描述入口的对象。你可以使用如下属性:
①dependOn: 当前入口所依赖的入口。它们必须在该入口被加载前被加载。
②filename: 指定要输出的文件名称。
③import: 启动时需加载的模块。
④library: library 的相关选项。
⑤runtime: 运行时 chunk 的名字。如果设置了,就会创建一个以这个名字命名的运行时 chunk,否则将使用现有的入口作为运行时。
注意:runtime 和 dependOn 不应在同一个入口上同时使用,所以如下配置无效,并且会抛出错误:
默认值是./src/index.js,但你可以通过在webpack configuration中配置entry属性,来指定一个(或多个)不同的入口起点:
webpack.config.js文件中: module.exports = { entry: './path/to/my/entry/file.js', }; |
output 属性告诉webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。
主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。
注意:即使可以存在多个 entry 起点,但只能指定一个 output 配置。
你可以通过在配置中指定一个 output 字段,来配置这些处理过程:
webpack.config.js文件中: const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js', }, }; |
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。
loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
在更高层面,在 webpack 的配置中,loader 有两个属性:
①test 属性,识别出哪些文件会被转换。
②use 属性,定义出在进行转换时,应该使用哪个 loader。
webpack.config.js文件中: const path = require('path'); module.exports = { output: { filename: 'my-first-webpack.bundle.js', }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' }, { test: /\.css$/, use: 'css-loader' }, { test: /\.ts$/, use: 'ts-loader' }, ], }, }; |
注意:
①在 webpack 配置中定义 rules 时,要定义在 module.rules。
②使用正则表达式匹配文件时,你不要为它添加引号。
1.2.3.1使用loader有3种方式
①配置方式(推荐):在 webpack.config.js文件中指定 loader:module.rules允许你在webpack配置中指定多个loader。 这种方式是展示loader的一种简明方式,并且有助于使代码变得简洁和易于维护。同时让你对各个loader有个全局概览,loader 从右到左(或从下到上)地取值(evaluate)/执行(execute);
②内联方式:在每个import语句中显式指定loader:可以在 import语句或任何与"import"方法同等的引用方式中指定loader。使用!将资源中的loader分开。每个部分都会相对于当前目录解析
使用!前缀,将禁用所有已配置的normal loader(普通loader)
使用!!前缀,将禁用所有已配置的loader(preLoader, loader, postLoader)
使用-!前缀,将禁用所有已配置的preLoader和loader,但是不禁用postLoaders
③CLI方式:在shell命令中指定它们。
1.2.3.2.loader特性
①loader 支持链式调用。链中的每个 loader 会将转换应用在已处理过的资源上。一组链式的 loader 将按照相反的顺序执行。链中的第一个 loader 将其结果(也就是应用过转换后的资源)传递给下一个 loader,依此类推。最后,链中的最后一个 loader,返回 webpack 所期望的 JavaScript。
②loader 可以是同步的,也可以是异步的。
③loader 运行在 Node.js 中,并且能够执行任何操作。
④loader 可以通过 options 对象配置(仍然支持使用 query 参数来设置选项,但是这种方式已被废弃)。
⑤除了常见的通过 package.json 的 main 来将一个 npm 模块导出为 loader,还可以在 module.rules 中使用 loader 字段直接引用一个模块。
⑥插件(plugin)可以为 loader 带来更多特性。
⑦loader 能够产生额外的任意文件。
1.2.3.3.解析loader
loader 遵循标准 模块解析 规则。多数情况下,loader 将从 模块路径 加载(通常是从 npm install, node_modules 进行加载)。
我们预期 loader 模块导出为一个函数,并且编写为 Node.js 兼容的 JavaScript。通常使用 npm 进行管理 loader,但是也可以将应用程序中的文件作为自定义 loader。
loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
插件目的在于解决 loader 无法实现的其他事。webpack 插件是一个具有apply方法的JavaScript对象。apply方法会被webpack compiler调用,并且在整个编译生命周期都可以访问compiler对象。
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。
由于插件可以携带参数/选项,你必须在 webpack配置中,向 plugins属性传入一个new实例。取决于你的 webpack 用法,对应有多种使用插件的方式。
多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建一个插件实例。
webpack.config.js文件中: const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装 const webpack = require('webpack'); // 用于访问内置插件 module.exports = { module: { rules: [{ test: /\.txt$/, use: 'raw-loader' }], }, plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })], }; |
通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。
webpack.config.js文件中: module.exports = { mode: 'production', }; |
webpack 支持所有符合 ES5 标准 的浏览器(不支持 IE8 及以下版本)。webpack 的 import() 和 require.ensure() 需要 Promise。
webpack 5 运行于 Node.js v10.13.0+ 的版本
你可能已经注意到,很少有 webpack 配置看起来完全相同。这是因为 **webpack 的配置文件是 JavaScript 文件,文件内导出了一个 webpack 配置的对象。**webpack 会根据该配置定义的属性进行处理。
由于 webpack 遵循 CommonJS 模块规范,因此,你可以在配置中使用:
通过 require(...) 引入其他文件
通过 require(...) 使用 npm 下载的工具函数
使用 JavaScript 控制流表达式,例如 ?: 操作符
对 value 使用常量或变量赋值
编写并执行函数,生成部分配置
resolver 是一个帮助寻找模块绝对路径的库。
resolver帮助webpack从每个require/import语句中,找到需要引入到bundle中的模块代码。当打包模块时,webpack使用 enhanced-resolve来解析文件路径。
绝对路径:由于已经获得文件的绝对路径,则直接去解析;
相对路径:在这种情况下,使用import或require的资源文件所处的目录,被认为是上下文目录。在import/require中给定的相对路径,会拼接此上下文路径,来生成模块的绝对路径。
模块路径:在 resolve.modules 中指定的所有目录来检索模块。 你可以通过配置别名的方式来替换初始模块路径。
如果package中包含package.json文件,那么在 resolve.exportsFields配置选项中指定的字段会被依次查找,package.json中的第一个字段会根据package导出指南确定 package中可用的 export。
一旦根据上述规则解析路径后,resolver将会检查路径是指向文件还是文件夹。如果路径指向文件:
①如果文件具有扩展名,则直接将文件打包。
②否则,将使用 resolve.extensions 选项作为文件扩展名来解析,此选项会告诉解析器在解析中能够接受那些扩展名。
如果路径指向一个文件夹,则进行如下步骤寻找具有正确扩展名的文件:
①如果文件夹中包含 package.json 文件,则会根据 resolve.mainFields 配置中的字段顺序查找,并根据 package.json 中的符合配置要求的第一个字段来确定文件路径。
②如果不存在 package.json 文件或 resolve.mainFields 没有返回有效路径,则会根据 resolve.mainFiles 配置选项中指定的文件名顺序查找,看是否能在 import/require 的目录下匹配到一个存在的文件名。
③然后使用 resolve.extensions 选项,以类似的方式解析文件扩展名
多个独立的构建可以组成一个应用程序,这些独立的构建之间不应该存在依赖关系,因此可以单独开发和部署它们。
这通常被称作微前端,但并不仅限于此。
我们分为本地模块、远程模块。
其中本地模块即为普通模块,是当前构建的一部分;而远程模块不属于当前构建,并在运行时从所谓的容器加载。
加载远程模块被认为是异步操作。当使用远程模块时,这些异步操作将被放置在远程模块和入口之间的下一个chunk的加载操作中。如果没有chunk加载操作,就不能使用远程模块。
chunk的加载操作通常是通过调用import()实现的,但也支持像 require.ensure或require([...])之类的旧语法。
容器是由容器入口创建的,该入口暴露了对特定模块的异步访问。暴露的访问分为两个步骤:
步骤1:加载模块(异步的)
步骤2:执行模块(同步的)
步骤1将在chunk加载期间完成。步骤2将在与其他(本地和远程)的模块交错执行期间完成。这样一来,执行顺序不受模块从本地转换为远程或从远程转为本地的影响。
容器可以嵌套使用,容器可以使用来自其他容器的模块。容器之间也可以循环依赖。
容器能够将选定的本地模块标记为“可重载”。容器的使用者能够提供“重载”,即替换容器中的一个“可重载”的模块。当使用者提供重载模块时,容器的所有模块将使用替换模块而非本地模块。当使用者不提供替换模块时,容器的所有模块将使用本地模块。
每个构建都充当一个容器,也可将其他构建作为容器。通过这种方式,每个构建都能够通过从对应容器中加载模块来访问其他容器暴露出来的模块。
每当一个文件依赖另一个文件时,webpack 都会将文件视为直接存在 依赖关系。这使得 webpack 可以获取非代码资源,如 images 或 web 字体等。并会把它们作为 依赖 提供给应用程序。
当 webpack 处理应用程序时,它会根据命令行参数中或配置文件中定义的模块列表开始处理。 从 入口 开始,webpack 会递归的构建一个_依赖关系图_,这个依赖图包含着应用程序中所需的每个模块,然后将所有模块打包为少量的 bundle —— 通常只有一个 —— 可由浏览器加载。
由于JavaScript即可以编写服务端代码也可以编写浏览器代码,所以 webpack 提供了多种部署 target,你可以在 webpack 的配置选项中进行设置。
想设置 target 属性,只需在 webpack 配置文件webpack.config.js中设置 target 字段:
在使用 webpack 构建的典型应用程序或站点中,有三种主要的代码类型:
①你或你的团队编写的源码。
②你的源码会依赖的任何第三方的library或"vendor"代码。
③webpack的runtime和manifest,管理所有模块的交互。
runtime:runtime以及伴随的 manifest 数据,主要是指:在浏览器运行过程中,webpack 用来连接模块化应用程序所需的所有代码。它包含:在模块交互时,连接模块所需的加载和解析逻辑。包括:已经加载到浏览器中的连接模块逻辑,以及尚未加载模块的延迟加载逻辑。
manifest:当 compiler 开始执行、解析和映射应用程序时,它会保留所有模块的详细要点。这个数据集合称为 "manifest",当完成打包并发送到浏览器时,runtime 会通过 manifest 来解析和加载模块。无论你选择哪种 模块语法,那些 import 或 require 语句现在都已经转换为 __webpack_require__ 方法,此方法指向模块标识符(module identifier)。通过使用 manifest 中的数据,runtime 将能够检索这些标识符,找出每个标识符背后对应的模块。
模块热替换(HMR - hot module replacement)功能会在应用程序运行过程中,替换、添加或删除 模块,而无需重新加载整个页面。主要是通过以下几种方式,来显著加快开发速度:
①保留在完全重新加载页面期间丢失的应用程序状态。
②只更新变更内容,以节省宝贵的开发时间。
③在源代码中 CSS/JS 产生修改时,会立刻在浏览器中进行更新,这几乎相当于在浏览器 devtools 直接更改样式。
CLI服务是构建于webpack和webpack-dev-server之上的。
安装:
npm install -g @vue/cli
yarn global add @vue/cli
查看版本:
vue --version
升级:
npm update -g @vue/cli
yarn global upgrade --latest @vue/cli
升级项目中的Vue CLI相关模块:
用法: upgrade [options] [plugin-name]
选项:
-t, --to
-f, --from
-r, --registry
--all 升级所有的插件
--next 检查插件新版本时,包括 alpha/beta/rc 版本在内
-h, --help 输出帮助内容
可以使用vue serve和vue build命令对单个*.vue文件进行快速原型开发,不过这需要先额外安装一个cli-service-global全局的扩展;
(这种模式下就用到2个命令:vue serve和vue build)
vue serve的缺点就是它需要安装全局依赖,这使得它在不同机器上的一致性不能得到保证。因此这只适用于快速原型开发。
vue serve
Usage: serve [options] [entry] 在开发环境模式下零配置为 .js 或 .vue 文件启动一个服务器 Options: -o, --open 打开浏览器 -c, --copy 将本地 URL 复制到剪切板 -h, --help 输出用法信息 |
在这个 App.vue文件所在的目录下运行:vue serve
vue serve 使用了和 vue create 创建的项目相同的默认设置 (webpack、Babel、PostCSS 和 ESLint)。它会在当前目录自动推导入口文件——入口可以是 main.js、index.js、App.vue 或 app.vue 中的一个。你也可以显式地指定入口文件:vue serve MyComponent.vue
如果需要,你还可以提供一个 index.html、package.json、安装并使用本地依赖、甚至通过相应的配置文件配置 Babel、PostCSS 和 ESLint。
vue build
Usage: build [options] [entry] 在生产环境模式下零配置构建一个 .js 或 .vue 文件 Options: -t, --target -n, --name -d, --dest -h, --help 输出用法信息 |
(用vue create、vue ui来创建新项目)
基于vue create创建
Usage: build [options] [entry] 用法:create [options] 创建一个由 `vue-cli-service` 提供支持的新项目 选项: -p, --preset -d, --default 忽略提示符并使用默认预设选项 -i, --inlinePreset -m, --packageManager -r, --registry -g, --git [message] 强制 / 跳过 git 初始化,并可选的指定初始化提交信息 -n, --no-git 跳过 git 初始化 -f, --force 覆写目标目录可能存在的配置 -c, --clone 使用 git clone 获取远程预设选项 -x, --proxy 使用指定的代理创建项目 -b, --bare 创建项目时省略默认组件中的新手指导信息 -h, --help 输出使用帮助信息 |
基于vue ui创建
可以通过vue ui命令以图形化界面创建和管理项目
拉取 2.x 模板 (旧版本)
Vue CLI >= 3 和旧版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能,你可以全局安装一个桥接工具:
npm install -g @vue/cli-init
# `vue init` 的运行效果将会跟 `[email protected]` 相同
vue init webpack my-project
2.3.3.1.简介
Vue CLI使用了一套基于插件的架构。如果你查阅一个新创建项目的 package.json,就会发现依赖都是以 @vue/cli-plugin- 开头的。插件可以修改 webpack 的内部配置,也可以向 vue-cli-service 注入命令。在项目创建的过程中,绝大部分列出的特性都是通过插件来实现的。
2.3.3.2.在现有的项目中安装插件
每个CLI插件都会包含一个(用来创建文件的)生成器和一个 (用来调整webpack核心配置和注入命令的)运行时插件。
当你使用vue create来创建一个新项目的时候,有些插件会根据你选择的特性被预安装好。
如果你想在一个已经被创建好的项目中安装一个插件,可以使用 vue add命令,举个例子:
vue add eslint
这个命令将@vue/eslint解析为完整的包名 @vue/cli-plugin-eslint,然后从npm安装它,调用它的生成器,因此,该命令可以等价于:vue add cli-plugin-eslint
2.3.3.3.项目本地的插件
如果你需要在项目里直接访问插件 API 而不需要创建一个完整的插件,你可以在 package.json 文件中使用 vuePlugins.service 选项;
你也可以通过 vuePlugins.ui 选项添加像 UI 插件一样工作的文件
2.3.4.1.简介
一个 Vue CLI preset是一个包含创建新项目所需预定义选项和插件的JSON对象,让用户无需在命令提示中选择它们。
在vue create过程中保存的preset会被放在你的home目录下的一个配置文件中(~/.vuerc)。你可以通过直接编辑这个文件来调整、添加、删除保存好的preset。
Preset的数据会被插件生成器用来生成相应的项目文件。这些额外的配置将会根据useConfigFiles的值被合并到package.json 或相应的配置文件中。
2.3.4.2.Preset插件的版本管理
可以显式地指定用到的插件的版本,例如:
{ "plugins": { "@vue/cli-plugin-eslint": { "version": "^3.0.0", // ... 该插件的其它选项 } } } |
2.3.4.3.允许插件的命令提示
每个插件在项目创建的过程中都可以注入它自己的命令提示,不过当你使用了一个 preset,这些命令提示就会被跳过,因为 Vue CLI 假设所有的插件选项都已经在 preset 中声明过了。
在有些情况下你可能希望 preset 只声明需要的插件,同时让用户通过插件注入的命令提示来保留一些灵活性。
对于这种场景你可以在插件选项中指定 "prompts": true 来允许注入命令提示:
{ "plugins": { "@vue/cli-plugin-eslint": { // 让用户选取他们自己的 ESLint config "prompts": true } } } |
2.3.4.4.远程Preset
你可以通过发布git repo将一个preset分享给其他开发者。这个repo应该包含以下文件:
preset.json: 包含preset数据的主要文件(必需)。
generator.js: 一个可以注入或是修改项目中文件的 Generator。
prompts.js 一个可以通过命令行对话为generator收集选项的 prompts文件。
发布repo后,你就可以在创建项目的时候通过--preset选项使用这个远程的preset了,GitLab和BitBucket也是支持的。如果要从私有repo获取,请确保使用--clone选项;
2.3.4.5.加载文件系统中的Preset
当开发一个远程preset的时候,你必须不厌其烦的向远程repo 发出push进行反复测试。为了简化这个流程,你也可以直接在本地测试preset。如果--preset选项的值是一个相对或绝对文件路径,或是以 .json 结尾,则 Vue CLI会加载本地的 preset
2.3.5.1.使用命令
在一个 Vue CLI 项目中,@vue/cli-service 安装了一个名为 vue-cli-service 的命令。你可以在 npm scripts 中以 vue-cli-service、或者从终端中以 ./node_modules/.bin/vue-cli-service 访问这个命令。
这是你使用默认 preset 的项目的 package.json:
{ "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build" } } |
可以通过 npm 或 Yarn 调用这些 script:
npm run serve
yarn serve
2.3.5.2.vue-cli-service serve
用法:vue-cli-service serve [options] [entry] 选项: --open 在服务器启动时打开浏览器 --copy 在服务器启动时将 URL 复制到剪切版 --mode 指定环境模式 (默认值:development) --host 指定 host (默认值:0.0.0.0) --port 指定 port (默认值:8080) --https 使用 https (默认值:false) |
vue-cli-service serve 命令会启动一个开发服务器 (基于 webpack-dev-server) 并附带开箱即用的模块热重载 (Hot-Module-Replacement)。
除了通过命令行参数,你也可以使用 vue.config.js 里的 devServer 字段配置开发服务器。
命令行参数 [entry] 将被指定为唯一入口,而非额外的追加入口。尝试使用 [entry] 覆盖 config.pages 中的 entry 将可能引发错误。
2.3.5.3.vue-cli-service build
用法:vue-cli-service build [options] [entry|pattern] 选项: --mode 指定环境模式 (默认值:production) --dest 指定输出目录 (默认值:dist) --modern 面向现代浏览器带自动回退地构建应用 --target app | lib | wc | wc-async (默认值:app) --name 库或 Web Components 模式下的名字 (默认值:package.json 中的 "name" 字段或入口文件名) --no-clean 在构建项目之前不清除目标目录 --report 生成 report.html 以帮助分析包内容 --report-json 生成 report.json 以帮助分析包内容 --watch 监听文件变化 |
vue-cli-service build 会在 dist/ 目录产生一个可用于生产环境的包,带有 JS/CSS/HTML 的压缩,和为更好的缓存而做的自动的 vendor chunk splitting。它的 chunk manifest 会内联在 HTML 里。这里还有一些有用的命令参数:
--modern 使用现代模式构建应用,为现代浏览器交付原生支持的 ES2015 代码,并生成一个兼容老浏览器的包用来自动回退。
--target 允许你将项目中的任何组件以一个库或 Web Components 组件的方式进行构建。更多细节请查阅构建目标。
--report 和 --report-json 会根据构建统计生成报告,它会帮助你分析包中包含的模块们的大小。
2.3.5.4.vue-cli-service inspect
用法:vue-cli-service inspect [options] [...paths] 选项: --mode 指定环境模式 (默认值:development) |
2.3.5.5.查看所有的可用命令
npx vue-cli-service help
npx vue-cli-service help [command]
2.3.5.6.缓存和并行处理
①cache-loader会默认为Vue/Babel/TypeScript编译开启。文件会缓存在node_modules/.cache中——如果你遇到了编译方面的问题,记得先删掉缓存目录之后再试试看。
②thread-loader会在多核CPU的机器上为Babel/TypeScript转译开启。
2.3.5.7.配置时无需 Eject
通过 vue create 创建的项目无需额外的配置就已经可以跑起来了。插件的设计也是可以相互共存的,所以绝大多数情况下,你只需要在交互式命令提示中选取需要的功能即可。
不过我们也知道满足每一个需求是不太可能的,而且一个项目的需求也会不断改变。通过 Vue CLI 创建的项目让你无需 eject 就能够配置工具的几乎每个角落。
2.4.1.1.browserslist
你会发现有 package.json 文件里的 browserslist 字段 (或一个单独的 .browserslistrc 文件),指定了项目的目标浏览器的范围。这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。
2.4.1.2.Polyfill
Babel是一个广泛使用的转码器,可以将ES6代码转为ES5代码。
2.4.2.1.HTML
2.4.2.1.1.Index文件
public/index.html文件是一个会被html-webpack-plugin处理的模板。在构建过程中,资源链接会被自动注入。另外,Vue CLI也会自动注入resource hint (preload/prefetch、manifest 和图标链接以及构建过程中处理的 JavaScript 和 CSS 文件的资源链接)
2.4.2.1.2.插值
因为index文件被用作模板,所以你可以使用 lodash template 语法插入内容:
<%= VALUE %> 用来做不转义插值;
<%- VALUE %> 用来做 HTML 转义插值;
<% expression %> 用来描述 JavaScript 流程控制。
除了被html-webpack-plugin暴露的默认值之外,所有客户端环境变量也可以直接使用;
2.4.2.1.3.Preload
是一种 resource hint,用来指定页面加载后很快会被用到的资源,所以在页面加载的过程中,我们希望在浏览器开始主体渲染之前尽早 preload。
默认情况下,一个 Vue CLI 应用会为所有初始化渲染需要的文件自动生成 preload 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的 config.plugin('preload') 进行修改和删除。
2.4.2.1.4.Prefetch
是一种 resource hint,用来告诉浏览器在页面加载完成后,利用空闲时间提前获取用户未来可能会访问的内容。
默认情况下,一个 Vue CLI 应用会为所有作为 async chunk 生成的 JavaScript 文件 (通过动态 import() 按需 code splitting 的产物) 自动生成 prefetch 提示。
这些提示会被 @vue/preload-webpack-plugin 注入,并且可以通过 chainWebpack 的 config.plugin('prefetch') 进行修改和删除。
Prefetch链接将会消耗带宽。如果你的应用很大且有很多 async chunk,而用户主要使用的是对带宽较敏感的移动端,那么你可能需要关掉 prefetch 链接并手动选择要提前获取的代码区块。
2.4.2.1.5.不生成index
当基于已有的后端使用Vue CLI时,你可能不需要生成 index.html,这样生成的资源可以用于一个服务端渲染的页面。
然而这样做并不是很推荐,因为:
①硬编码的文件名不利于实现高效率的缓存控制。
②硬编码的文件名也无法很好的进行 code-splitting (代码分段),因为无法用变化的文件名生成额外的 JavaScript 文件。
③硬编码的文件名无法在现代模式下工作。
你应该考虑换用 indexPath 选项将生成的 HTML 用作一个服务端框架的视图模板。
2.4.2.1.6.构建一个多页应用
Vue CLI 支持使用 vue.config.js 中的 pages 选项构建一个多页面的应用。构建好的应用将会在不同的入口之间高效共享通用的 chunk 以获得最佳的加载性能。
2.4.2.2.处理静态资源
静态资源可以通过两种方式进行处理:
①在JavaScript被导入或在template/CSS中通过相对路径被引用。这类引用会被webpack处理。
②放置在public目录下或通过绝对路径被引用。这类资源将会直接被拷贝,而不会经过webpack的处理。
2.4.2.2.1.从相对路径导入
当在文件中使用相对路径(必须以.开头)引用一个静态资源时,该资源将会被包含进入webpack的依赖图中。在其编译过程中,所有诸如、background: url(...) 和CSS @import的资源URL都会被解析为一个模块依赖。
例如,url(./image.png)会被翻译为require('./image.png')
在其内部,通过file-loader用版本哈希值和正确的公共基础路径来决定最终的文件路径,再用url-loader将小于4kb的资源内联,以减少HTTP请求的数量。可以通过chainWebpack调整内联文件的大小限制。
2.4.2.2.2.URL转换规则
①如果 URL 是一个绝对路径 (例如 /images/foo.png),它将会被保留不变。
②如果 URL 以 . 开头,它会作为一个相对模块请求被解释且基于你的文件系统中的目录结构进行解析。
③如果 URL 以 ~ 开头,其后的任何内容都会作为一个模块请求被解析。这意味着你甚至可以引用 Node 模块中的资源:
④如果 URL 以 @ 开头,它也会作为一个模块请求被解析。它的用处在于 Vue CLI 默认会设置一个指向
2.4.2.2.3.public文件夹
任何放置在public文件夹的静态资源都会被简单的复制,而不经过webpack。你需要通过绝对路径来引用它们。
注意我们推荐将资源作为你的模块依赖图的一部分导入,这样它们会通过webpack的处理并获得如下好处:
①脚本和样式表会被压缩且打包在一起,从而避免额外的网络请求。
②文件丢失会直接在编译时报错,而不是到了用户端才产生 404 错误。
③最终生成的文件名包含了内容哈希,因此你不必担心浏览器会缓存它们的老版本。
public目录提供的是一个应急手段,当你通过绝对路径引用它时,留意应用将会部署到哪里。如果你的应用没有部署在域名的根部,那么你需要为你的URL配置publicPath前缀;
2.4.2.2.4.何时使用public文件夹
①你需要在构建输出中指定一个文件的名字。
②你有上千个图片,需要动态引用它们的路径。
③有些库可能和 webpack 不兼容,这时你除了将其用一个独立的