本文已获得原作者的独家授权,有想转载的朋友们可以在后台联系我申请开白哦!
PS:欢迎掘友们向我投稿哦,被采用的文章还可以送你掘金精美周边!
想必绝大多数用 Vue
开发过项目的同学,或多或少会有以下两种情况:
用 Vue CLI
工具去搭建一个项目。
在领导或同事搭建好的项目基础上做业务。
长此以往,会导致你对整个项目的把控度越来越低。面试下一家公司的面试官问你,是否手动搭建过 Vue
项目的时候,对配置一问三不知????️ 。本文着重为大家讲解从 0 到 1 搭建 Vue 3.x
开发环境 的过程中遇到的疑问。
这里提前说明,本文侧重新手向,只搭建了开发环境,主要是让大家了解一个过程,是一篇入门级别的文章,大佬对自己够自信的话,就看到这里,就此作罢。
本文章源码:https://github.com/Nick930826/hand-vue3-project
新蜂商城开源仓库:https://github.com/newbee-ltd(内涵 Vue 2.x 和 Vue 3.x 的 H5 商城开源代码)
Vue 3.x + Vant 3.x 高仿微信记账本开源地址:https://github.com/Nick930826/daily-cost
原创不易,有帮助的还望点赞支持,这将是我持续原创输出的动力。还有,打榜别给我投票,我还差这点钱吗?
我们先抛开 Vue
,针对 Webpack
先搭建一个项目最初的模样,在你喜欢的目录下新建一个文件夹,并初始化项目:
// 创建文件夹
mkdir hand-vue3-project && cd hand-vue3-project
// 初始化项目
npm init -y
此时你将会得到一个只有 package.json
文件的项目,接下来我们安装 webpack
和 webpack-cli
,命令行如下:
yarn add webpack webpack-cli -D
webpack-cli 是执行 webpack 的工具。webpack 4.x 版本以后,剥离出了 webpack-cli ,所以这里我们需要单独下载它。
接下来在根目录添加如下 src
文件夹,并且在 src
文件夹内添加 main.js
文件,内容我们先不添加。再在根目录添加 index.html
和 webpack.config.js
,添加完后结构如下所示:
接下来我们给 webpack.config.js
添加内容:
// webpack.config.js
const path = require('path')module.exports = {mode: 'development', // 环境模式entry: path.resolve(__dirname, './src/main.js'), // 打包入口output: {path: path.resolve(__dirname, 'dist'), // 打包出口filename: 'js/[name].js' // 打包完的静态资源文件名}
}
修改 package.json
的 scripts
属性:
"scripts": {"dev": "webpack --config ./webpack.config.js"
}
运行打包指令 yarn dev
, 如下所示代表成功:
图中的 js/main.js
就是我们通过 webpack
将 main.js
打包完后的代码,打开之后你会发现里面啥都没有,接下来我们给 index.html
添加内容,然后通过 html-webpack-plugin
插件,将 index.html
作为模板,打出到 dist
文件夹。
通过指令添加 html-webpack-plugin
插件:
yarn add html-webpack-plugin -D
在 webpack.config.js
下引入并使用:
const path = require('path')
const HtmlWebpackPlugin &#61; require(&#39;html-webpack-plugin&#39;)module.exports &#61; {mode: &#39;development&#39;,entry: path.resolve(__dirname, &#39;./src/main.js&#39;),output: {path: path.resolve(__dirname, &#39;dist&#39;),filename: &#39;js/[name].js&#39;},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, &#39;./index.html&#39;), // 我们要使用的 html 模板地址filename: &#39;index.html&#39;, // 打包后输出的文件名title: &#39;手搭 Vue 开发环境&#39; // index.html 模板内&#xff0c;通过 <%&#61; htmlWebpackPlugin.options.title %> 拿到的变量})]
}
上述是对 html-webpack-plugin
插件比较常用的描述&#xff0c;如果想深入了解配置项的同学请移步 Github官网 。 最后我们给 index.html
加上内容&#xff1a;
给 main.js
来点内容&#xff1a;
const root &#61; document.getElementById(&#39;root&#39;)
root.textContent &#61; &#39;你妈贵姓&#xff1f;&#39;
运行打包指令 yarn dev
&#xff0c;我们来看看 dist
目录下会多出什么&#xff1a;
我们不妨直接在浏览器打开 index.html
看看&#xff0c;会有什么效果&#xff1a;
这么一想&#xff0c;大家结合我前面那篇《你好&#xff0c;谈谈你对前端路由的理解》, 完全就可以直接在 main.js
里开始敲页面了。 js
功底好的同学&#xff0c;可以直接通过 js
的 DOM
操作能力&#xff0c;创建标签塞入 root
节点。
这合适吗&#xff1f;谁让我这么干&#xff0c;我就一套五连鞭&#xff0c;抽它。
稍作思考之后&#xff0c;我便义无反顾地选择引入 Vue
。
引入 Vue 3.x
&#xff0c;指令如下&#xff1a;
yarn add vue&#64;next -S
这里注意&#xff0c;要使用 vue&#64;next 才能成功引入 Vue 3.x&#xff0c;否则就会引入 2.x 的最高版本。这里 -S 是指生产环境需要用到的包 — dependencies。同理 -D 表示开发环境需要的依赖。
引入成功之后&#xff0c;我们在 src
目录下新建 App.vue
&#xff1a;
瞧瞧&#xff0c;正儿八经的 Vue
模板页面。我现在想把它引入到 root
节点下&#xff0c;怎么玩&#xff1f; 打开 main.js
添加如下内容&#xff1a;
import { createApp } from &#39;vue&#39; // Vue 3.x 引入 vue 的形式
import App from &#39;./App.vue&#39; // 引入 APP 页面组建const app &#61; createApp(App) // 通过 createApp 初始化 app
app.mount(&#39;#root&#39;) // 将页面挂载到 root 节点
整完之后&#xff0c;我快乐的去打包&#xff0c;给我报了个错。
大致意思就是说&#xff0c;“您可能需要适当的 loader
程序来处理 .vue
文件类型&#xff0c;当前没有配置任何 loader
来处理此文件。” 此时我准备用 **脑子 **想一想&#xff0c;让浏览器去识别 .vue
结尾的文件&#xff0c;这不合适。我们必须让它变成浏览器认识的语言&#xff0c;那就是 js
&#xff0c;于是我们需要添加下面几个插件&#xff1a;
vue-loader&#xff1a;它是基于 webpack
的一个的 loader
插件&#xff0c;解析和转换 .vue
文件&#xff0c;提取出其中的逻辑代码 script
、样式代码 style
、以及 HTML
模版 template
&#xff0c;再分别把它们交给对应的 loader
去处理如 style-loader
、 less-loader
等等&#xff0c;核心的作用&#xff0c;就是 提取
。
&#64;vue/compiler-sfc&#xff1a; Vue 2.x
时代&#xff0c;需要 vue-template-compiler
插件处理 .vue
内容为 ast
&#xff0c; Vue 3.x
则变成 &#64;vue/compiler-sfc
。
安装的时候注意 vue-loader 需要通过 yarn add vue-loader&#64;next 安装最新版本。
然后我们为 webpack.config.js
添加如下内容&#xff1a;
const path &#61; require(&#39;path&#39;)
const HtmlWebpackPlugin &#61; require(&#39;html-webpack-plugin&#39;)
// 最新的 vue-loader 中&#xff0c;VueLoaderPlugin 插件的位置有所改变
const { VueLoaderPlugin } &#61; require(&#39;vue-loader/dist/index&#39;)module.exports &#61; {mode: &#39;development&#39;,entry: path.resolve(__dirname, &#39;./src/main.js&#39;),output: {path: path.resolve(__dirname, &#39;dist&#39;),filename: &#39;js/[name].js&#39;},module: {rules: [{test: /\.vue$/,use: [&#39;vue-loader&#39;]}]},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, &#39;./index.html&#39;),filename: &#39;index.html&#39;,title: &#39;手搭 Vue 开发环境&#39;}),// 添加 VueLoaderPlugin 插件new VueLoaderPlugin()]
}
VueLoaderPlugin
的职责是将你定义过的其它规则复制并应用到 .vue
文件里相应语言的块。例如&#xff0c;如果你有一条匹配 /\.js$/
的规则&#xff0c;那么它会应用到 .vue
文件里的
打包又回报错&#xff1a;
意思就是说&#xff0c;又少 loader
了&#xff0c;我们还需增加下面几个插件&#xff1a;
style-loader&#xff1a;将 css
样式插入到页面的 style
标签中。
css-loader&#xff1a;处理样式中的 url
&#xff0c;如 url(&#39;&#64;/static/img.png&#39;)
&#xff0c;这时浏览器是无法识别 &#64;
符号的。
这里插播一下&#xff0c;vue-style-loader 是服务端渲染的时候&#xff0c;需要的 loader&#xff0c;包括 less-loader、sass-loader 都是在用到的时候&#xff0c;才去添加。
安装完后&#xff0c;我们在 webpack.config.js
下添加如下代码&#xff1a;
module: {rules: [...{test: /\.css$/,use: [&#39;style-loader&#39;,&#39;css-loader&#39;]}...]
}
又可以快乐的打包了呢&#xff0c;打完后浏览器打开 index.html
如下所示&#xff1a;
还有一个小插件是必备的&#xff0c; clean-webpack-plugin
&#xff0c;它的作用就是每次打包的时候&#xff0c;都会把 dist
目录清空&#xff0c;防止文件变动后&#xff0c;还有残留一些老的文件&#xff0c;以及避免一些缓存问题。webpack.config.js
配置如下&#xff1a;
const { CleanWebpackPlugin } &#61; require(&#39;clean-webpack-plugin&#39;)
plugins: [new CleanWebpackPlugin()
]
讲到这&#xff0c; Vue 3.x
引入的部分就告一段落了&#xff0c;接下来我们再聊聊 babel
。
可以正常敲 Vue
代码之后&#xff0c;我们还要考虑一下代码的浏览器兼容情况&#xff0c;毕竟现代前端框架 Vue
、 React
、 Angular
等都是对浏览器有要求的。就比如 IE
全员不支持箭头函数&#xff0c;这你找谁说理。
图片来自 caniuse.com
以我自己的理解&#xff0c; babel
是把我们随心所欲&#xff08;最新特性一顿乱写&#xff09;写的代码&#xff0c;编译成浏览器可识别的代码&#xff08;低版本浏览器对新特性的支持不友好&#xff09;&#xff0c;就比如上述箭头函数&#xff0c;经过 babel
的转化后&#xff0c;就会变成普通的函数。
它有三种使用方式&#xff1a;
使用单体文件。
命令行&#xff08;babel-cli&#xff09;。
构建工具如 webpack
中的 babel-loader
插件。
我们前端常用的就是第三种&#xff0c;构建工具的插件形式。毕竟现在大多数前端项目都是基于 webpack
构建的。 这里我们不对 babel
做深究&#xff0c;不然要跑题了&#xff0c;下一篇再为大家细讲 babel
。 我们开始对上述项目做 babel
相关的配置&#xff0c;我们需要下面几个插件&#xff1a;
&#64;babel/core&#xff1a; babel
的核心库。
&#64;babel/preset-env&#xff1a;它取代了 es2015 es2016 es2017
&#xff0c;通过配置浏览器版本的形式&#xff0c;将编译的主动权&#xff0c;交给了插件。
babel-loader&#xff1a; webpack
的 loader
插件&#xff0c;用于编译代码&#xff0c;转化成浏览器读得懂的代码。
安装完上述插件之后&#xff0c;我们在 webpack.config.js
下添加如下代码&#xff1a;
module: {rules: [{test: /\.js$/,exclude: /node_modules/, // 不编译node_modules下的文件loader: &#39;babel-loader&#39;},]
}
编译的时候&#xff0c;需要读取配置&#xff0c;最新的 babel
配置文件需要在根目录下添加 babel.config.js
文件&#xff1a;
module.exports &#61; {presets: [["&#64;babel/preset-env", {"targets": {"browsers": ["last 2 versions"] // 最近 2 个版本的浏览器}}]]
}
这里 browsers 的配置&#xff0c;就是让 env 去识别要打包代码到什么程度&#xff0c;版本选的越新&#xff0c;打包出来的代码就越小。因为通常版本越低的浏览器&#xff0c;代码转译的量会更大。具体的配置可以参考 https://github.com/browserslist/browserslist
为了能体现出打包后的效果&#xff0c;我们在 App.vue
下添加一些代码&#xff1a;
然后我们运行打包指令 yarn dev
&#xff0c;打完包后我们浏览器打开 dist/index.html
查看代码&#xff1a;
箭头函数变成了普通函数。
我再将 babel.config.js
的目标浏览器配置改成如下所示&#xff1a;
module.exports &#61; {presets: [["&#64;babel/preset-env", {"targets": {"browsers": ["last 1 chrome version"]}}]]
}
因为我制定了谷歌最新版本&#xff0c;所以打包之后&#xff0c;代码并没有从箭头函数变为普通函数。
每次写完代码都要重新打包才能看到效果&#xff0c;“TMD 烦死了”。这里需要一个实时更新最新代码的能力。于是 webpack-dev-server
为我们实现了这个能力。 安装它&#xff1a;
yarn add webpack-dev-server -D
在 webpack.config.js
下添加如下配置&#xff1a;
devServer: {contentBase: path.resolve(__dirname, &#39;./dist&#39;),port: 8080,publicPath: &#39;/&#39;
}
修改 package.json
运行脚本&#xff1a;
"scripts": {"dev": "webpack serve --progress --config ./webpack.config.js"
}
注意了啊&#xff0c;webpack-cli 升级到 4.x 的时候&#xff0c;就不能用 webpack-dev-server 跑脚本了&#xff0c;而是改为 webpack serve 去跑。
成功之后如下所示&#xff1a;
此时静态资源 main.js 跑在浏览器的内存里&#xff0c;热更新的速度那是相当快啊。
本文主要是将讲解一个搭建 Vue 3
可运行的最小单位&#xff0c;所以还有不少配置需要添加&#xff0c;如 file-loader
、 url-loader
、 &#64;babel/polyfill
等等等等。关注我的开源项目&#xff0c;后续会添加更多的配置&#xff0c;文中就不赘述了&#xff0c;祝大家工作学习愉快。
如果你觉得这篇内容对你挺有启发&#xff0c;我想邀请你帮我三个小忙&#xff1a;
点个「在看」&#xff0c;让更多的人也能看到这篇内容&#xff08;喜欢不点在看&#xff0c;都是耍流氓 -_-&#xff09;
欢迎加我微信「huab119」拉你进技术群&#xff0c;长期交流学习...
关注公众号「前端劝退师」&#xff0c;持续为你推送精选好文&#xff0c;也可以加我为好友&#xff0c;随时聊骚。
点个在看支持我吧&#xff0c;转发就更好了