哈喽大家好,我是haibin。这是我写的第一册技术小书,在掘金会分几篇发布,也可以直接点击下面在线访问全册,希望大家喜欢!
小书介绍
- 《从0到1搭建企业级vue3脚手架》在线访问
- 《从0到1搭建企业级vue3脚手架》项目源码
前言
以往像我们搭建vue项目,第一时间想到的就是vue-cli直接命令生成脚手架。
这种方式看似非常轻松、方便,平时写写业务代码或许无所谓,但直到需要你优化项目、解决原理层棘手问题的时候你才猛然发现,过于依赖这个工具反而会导致我们对于底层原理一概不知。这个时候就会措手不及,才逐渐开始去了解底层的部分。
与其到时被动,不如现在主动从0到1去搭建vue3脚手架!
这本小书会手把手地教你如何从“空文件夹”搭建到企业级脚手架。
起步
空文件夹
首先,我们来创建一个空文件夹。
mkdir vue3-scaffolding-tutorial-example
cd vue3-scaffolding-tutorial-example
说明文档
接着创建README.md
文件,用于项目说明。
# vue3-scaffolding-tutorial-example
git忽略配置
接着是git忽略配置文件.gitignore
,Github官方提供了不同环境下的.gitignore模板
我们这里直接使用提供的Node.gitignore
即可。
index.html
模仿Vue Cli的目录结构创建public和src目录
mkdir public
mkdir src
顺便也把最基础的index.html也创建了吧,放到public/index.html
vue3-scaffolding-tutorial-example
package.json
npm的由来
在GitHub还没有兴起的年代,前端是通过网址来共享代码。比如说你想使用jQuery
,那么你得点击jQuery网站上提供的链接来下载jQuery,再放到自己的网站上使用。
到GItHub兴起之后,社区中也有人使用GitHub的下载功能。但当一个网站依赖的代码越来越多,发现这是一件非常麻烦的事情:
- 去 jQuery官网 下载jQuery
- 去 BootStrap官网 下载BootStrap
- 去 Underscore官网 下载Underscore
- ...
有些程序员就受不鸟了,一个拥有三大美德的程序员 Isaac Z. Schlueter (上图)给出一个解决方案:用一个工具把这些代码集中到一起来进行管理。
后面跟Node.js的作者Ryan Dahl(上图)合作,成为Node.js内置的包管理器。
所以这个工具也就叫做npm
,全称是Node Package Manager
(运行在Node.js上的JavaScript程序),而我们待会要创建的package.json
也就是这个工具的包描述文件。
它的大致思路是:
- 让不同插件的作者通过npm publish把代码提交到registry上
- 社区里的其他人就想用这些插件,就把插件名写到包描述文件
package.json
里 - 运行
npm install
,npm就会帮他们下载代码到本地的node_modules
目录里
创建package.json
由于Node.js内置了npm,所以我们可以直接使用命令npm init -y
来进行创建。
会生成大致如下包含包自身描述的内容
{
"name": "vue3-scaffolding-tutorial-example",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/haibin-007/vue3-scaffolding-tutorial-example.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/haibin-007/vue3-scaffolding-tutorial-example/issues"
},
"homepage": "https://github.com/haibin-007/vue3-scaffolding-tutorial-example#readme"
}
构建工具的选择
既然是企业级脚手架,那么肯定得选择比较成熟且稳定的工具。
目前市场上比较合适的选项有:webpack、rollup、gulp、vite
...
无论从市场或功能层面,webpack都比较适合我们的场景。
Webpack
先把webpack包及其命令行工具安装了。
为了后续便于维护,我们专门建一个webpack目录。
npm i -D webpack webpack-cli
mkdir webpack
接着创建webpack/webpack.base.js
文件以及我们指向的入口文件src/index.js
。
// webpack/webpack.base.js
const path = require('path');
module.exports = {
entry: {
index: path.resolve(__dirname, '../src/index.js'),
},
output: {
path: path.resolve(__dirname, '../dist'),
}
}
// src/index.js
console.log('hello world!');
再创建webpack/webpack.dev.js
、webpack/webpack.prod.js
,针对于开发和生产环境的配置文件。
这里我们需要使用webpack-merge插件来合并配置项,webpack-dev-server用于提供开发环境服务。
npm i -D webpack-merge webpack-dev-server
// webpack/webpack.dev.js
const webpackMerge = require('webpack-merge');
const baseConfig = require('./webpack.base');
const path = require('path');
module.exports = webpackMerge.merge(baseConfig, {
mode: 'development',
devServer: {
host: '0.0.0.0',
port: 3000
},
});
// webpack/webpack.prod.js
const webpackMerge = require('webpack-merge');
const baseConfig = require('./webpack.base');
module.exports = webpackMerge.merge(baseConfig, {
mode: 'production'
});
再将开发和构建的命令加入到package.json。
"scripts": {
"dev": "webpack serve --config webpack/webpack.dev.js",
"build": "webpack --config webpack/webpack.prod.js"
},
尝试执行下命令npm run dev
结果我们看到它只是拿到我们本地的public/index.html
静态文件,并没有绑定src/index.js
。
所以这里我们需要用到一个webpack插件html-webpack-plugin
来生成已绑定的index.html
。
npm i -D html-webpack-plugin
// webpack.base.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: {
index: path.resolve(__dirname, '../src/index.js'),
},
output: {
path: path.resolve(__dirname, '../dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
favicon: path.resolve(__dirname, '../public/logo.svg'), // 顺便加入favicon
}),
]
}
由于它是生成在output指定的dist目录,所以我们还需配置webpack-dev-server的静态目录为dist。
// webpack.dev.js
devServer: {
host: '0.0.0.0',
port: 3000,
static: {
directory: path.join(__dirname, '../dist')
}
},
接着再执行npm run dev
我们则会看到已经绑定上了。
顺带一提,这个ws实际上就是webpack-dev-server
的热更新的通讯原理,通过websocket
侦测代码的变化,从而通知本地server进行更新。
再执行npm run build
试试。
npm run build
npm install -g http-server
http-server dist # 这里我们借助http-server访问dist来验证结果
结果如我们所愿跟dev的呈现结果一致,只是进一步对index.html
做了压缩。
ESLint
到这里我们算是把最基础的构建部分给弄好了。
既然要构建企业级的脚手架,代码的规范性肯定也少不了,这里我们选取当下前端最热门的代码规范检查工具ESLint
。
接着我们安装eslint
以及创建它的配置文件.eslintrc.js
,顺便也把.eslintignore
忽略文件也创建了
npm i -D eslint
// .eslintrc.js
module.exports = {
env: {
browser: true, // 支持浏览器环境
node: true, // 识别 CommonJS
es6: true, // 识别 ES 的代码
},
// 继承ESLint的规则集
extends: [
"eslint:recommended", // ESLint自带
]
};
// .eslintignore 需要时再添加配置项
我们要知道ESLint规则默认配置是没有限制的也就是无规则的,需要什么规范我们就自己手动去配置里加规则,这里使用了eslint
自身提供的规则集eslint:recommended
。
随意在src/index.js
里加代码试试效果。
console.log('hello world!');
const test = 123;
这里可以看到提示信息违反了规则no-unused-vars
,也就是不允许声明未使用的变量,再手动加上去使用就可以避免违反规则了。
console.log('hello world!');
const test = 123;
console.log(test);
但我们想象一下,如果每次有违反规则的时候我们都得手动去修复是不是特别麻烦?况且我们一般都是统一用业界写好的规则集,没有多少人会特地去熟悉这么多的规则。
那这个痛点我们该怎么来解决呢?
Prettier
这个痛点能够使用Prettier来解决,Prettier是通过结合eslint的规则来进行修复。
接着我们来安装prettier
,以及创建它的配置文件.prettierrc.js
。
npm i -D prettier
// .prettierrc.js
module.exports = {}
Prettier
和ESLint
完全不一样,它的默认配置并非是零,而是每个选项都有默认值,所以我们直接不进行配置即可。
加入一段代码来验证下效果
console.log("hello world!");
const test = 123;
console.log(test);
let a = 1;
const b = 2
const c = 333;
console.log('result'
,a,
b,
c)
执行如下命令即可生效
npx prettier --write .\src\index.js
console.log("hello world!");
const test = 123;
console.log(test);
let a = 1;
const b = 2;
const c = 333;
console.log("result", a, b, c);
通过命令来修复特别麻烦,所以我们通过结合编辑器插件来自动修复。
在vscode插件商店搜索prettier
即可找到对应插件,安装完后我们需要创建vscode的项目配置文件.vscode/settings.json
来覆盖默认配置。
// .vscode/settings.json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
配置了保存时格式化、使用prettier格式化两项,现在再保存文件就会自动使用prettier格式化了。
这时你会发现.eslintrc.js
文件保存时也被格式化了,之前的注释也不那么整齐了。
// .eslintrc.js
module.exports = {
env: {
browser: true, // 支持浏览器环境
node: true, // 识别 CommonJS
es6: true, // 识别 ES 的代码
},
// 继承ESLint的规则集
extends: [
"eslint:recommended", // ESLint自带
],
};
我们可以创建一个.prettierignore
忽略文件来跳过指定文件或目录:
// .prettierignore
.eslintrc.js
这样一来就不会被格式化了。
最后我们顺便将编辑器风格配置文件.editorconfig
也集成到prettier
中。
// .editorconfig
root = true
[*]
end_of_line = lf
charset = utf-8
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true
tab_width = 4
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
// .prettierrc.js
module.exports = {
useEditorConfig: true,
};
下图在vscode的Prettier插件输出中也可以看出配置生效了。
ESLint & Prettier
前面已经配置好了Prettier,接着就是将ESLint的规则使用到Prettier的格式化中。
需要安装两个插件:
npm i -D eslint-plugin-prettier eslint-config-prettier
-
eslint-plugin-prettier
作用是添加prettier的代码风格规则,使用prettier来自动修复代码 -
eslint-config-prettier
作用是用来禁用掉eslint部分与prettier相冲突的规则的
// .eslintrc.js
module.exports = {
env: {
browser: true, // 支持浏览器环境
node: true, // 识别 CommonJS
es6: true, // 识别 ES 的代码
},
// 继承ESLint的规则集
extends: [
"eslint:recommended", // ESLint自带
"plugin:prettier/recommended" // Prettier
]
};
这时error
的修复选项就会有prettier
了。
Webpack & ESLint
为了能够在构建过程中就能发现ESlint的错误,这里我们可以使用插件eslint-webpack-plugin
让ESLint
和Webpack
进行绑定。
npm i -D eslint-webpack-plugin
再在webpack/webpack.base.js
进行配置即可。
// webpack.base.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ESLintWebpackPlugin = require('eslint-webpack-plugin');
module.exports = {
entry: {
index: path.resolve(__dirname, '../src/index.js'),
},
output: {
path: path.resolve(__dirname, '../dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '../public/index.html'),
favicon: path.resolve(__dirname, '../public/logo.svg'), // 顺便加入favicon
}),
new ESLintWebpackPlugin({
extensions: ['js','ts','vue']
}),
]
}