了解vue-cli原理
vue-cli为vue的脚手架,它是一个专门为单页面应用快速搭建繁杂的脚手架,它可以轻松的创建新的应用程序而且可用于自动生成vue和webpack的项目模板。
很多人在学习或者写一个Vue的项目的时候,都是上来直接使用vue-cli搭建,直接vue init webpack project或者vue create project(vue-cli3)来创建项目,但是并不知道这背后到底是怎么创建的。
其实vue-cli就是一个模板下载器,把git上用webpack配置好的脚手架模板下到我们本地了,它会询问我们是否需要vue-router、vuex、axios、eslint等,根据我们的需求来进行配置,最核心的还是webpack。git上的官方模板在这里:传送门
如下图,可以看到目录结构是不是很熟悉。。。
学习如何从零搭建一个脚手架
webpack基础用法
废话不多说,首先创建一个项目,初始化一个package.json
mkdir vue-simple-cli && cd vue-simple-cli |
安装wbepack必备的包(webpack最新4+的版本需要安装cli)
创建一个webpack.config.js
npm i -D webpack webpack-cli |
在根目录创建index.html引入打包后的js方便看效果,创建src文件夹存放源文件,并在下面创建一个main.js,现在我们的目录结构看起来如下图所示:
然后开始写我们的webpack配置文件
const path = require('path') |
在main.js里面随便写点东西,在index.html去引入我们打包后的js。
console.log('hello webpack') |
|
然后执行webpack命令进行打包
npx webpack |
将index.html在浏览器中打开,查看控制台发现打印了hello webpack,证明第一步我们已经成功了。
开始引入Vue
安装vue模块
npm i -S vue |
给index.html加一个id为app的节点供vue挂载
|
修改main.js,引入vue模块,写一个简单的vue组件去引入,然后new一个vue实例挂在到app节点上
import Vue from 'vue/dist/vue.esm' // 引入vue的es module版本 |
打开index.html看到展示Hello World,证明这一步已经完成。
实现修改热更新
上面我们每次修改源文件都需要重新打包,然后刷新浏览器很麻烦,下面我们将基于webpack-dev-server实现一个修改热更新,起一个本地服务,每次修改main.js里面内容浏览器都会自动刷新到我们最新修改的状态。
安装webpack-dev-server
npm i -D webpack-dev-server |
然后在package.json的scripts里面写一个命令,简化操作.
"dev": "npx webpack-dev-server" // 加--open可以自动打开浏览器 |
在index.html中我们需要修改打包后文件的引入路径,由于我们使用了webpack-dev-server在本地起了一个服务,打包后的js其实是放在内存中的,相对于我们的服务器的地址,所以路径改为
现在我们执行熟悉的命令来启动我们的本地服务:
npm run dev |
通过 http://localhost:8080/ 就能访问到我们的页面了,现在修改main.js里面的组件的name属性,发现浏览器自动刷新展示我们修改后的结果。
区分开发模式和生产模式
在上面一步我们可以说是简单实现了开发模式下的做法,生产模式去打包生成文件,又需要修改index.html引入的js路径岂不是很麻烦,那么有没有办法自动的去修改呢?
html-webpack-plugin刚好就帮我们实现了这个功能。
npm i -D html-webpack-plugin |
修改我们的webpack.config.js配置
const path = require('path') |
在package.json增加打包的命令
"build": "npx webpack" |
现在可以把index.html中的引入js的script删掉了,html-webpack-plugin会帮我们做这件事情。
npm run build |
执行完熟悉的打包命令,发现在dist目录下把index.html也生成了,并且自动插入了一段js引入了我们打包后的js文件。
在浏览器中打开html文件发现没毛病,不过还没完,接下来才是重头戏,我们要修改webpack配置区分开发和生产的配置,根据我们执行的命令来决定使用开发模式还是生产模式。
首先新建一个config文件夹,在文件夹下面分别创建webpack.dev.conf.js和webpack.prod.conf.js。
修改我们package.json中的命令,增加环境变量的参数
"dev": "npx webpack-dev-server --env.mode=development", |
现在webpack.config.js里面之前的代码都可以删掉了,我们改写为如下代码:
module.exports = env => { |
执行npm run dev或者build可以看到打印出了我们写入的环境变量
现在我们已经能够知道当前的是开发还是生产模式,接下来开始改写webpack.config.js,这里只需要配置开发和生产都共有的配置项就可以,然后根据判断去引入开发还是生产的配置文件,进行合并配置项。
webpack.config.js
const modeOptions = { |
webpack.dev.conf.js
const HtmlWebpackPlugin = require('html-webpack-plugin') |
每次打包清理掉上次打包残留的文件还需要加一个clean-webpack-plugin
npm i -D clean-webpack-plugin |
webpack.prod.conf.js
const path = require('path') |
现在我们再来执行npm run dev和build发现是不是越来越接近vue-cli脚手架,但是还有点不一样,我们现在打包的都是js文件,正常我们vue实际项目里面都是vue文件。
各种loader
webpack本身只能识别js和json,但是它提供了各种loader插件可以将不能识别的文件解析成webpack能够识别的文件。
搭建vue脚手架我们需要如下的loader:
- css-loader 解析css文件
- vue-loader 解析vue文件
- vue-html-loader 解析vue内部的template
- vue-style-loader 解析vue内部的style,并把外部的css统一归vue管
- vue-template-compiler 编译器,把vue内的三大块编译成html、css、js
安装这些loader修改webpack.config.js,增加loader配置,顺便优化一下引入模块省去后缀名,设置别名。npm i -D css-loader vue-loader vue-html-loader vue-style-loader vue-template-compiler
在dev和prod配置文件中增加vue-loaderconst path = require('path')
const modeOptions = {
development: require('./config/webpack.dev.conf'),
production: require('./config/webpack.prod.conf')
}
module.exports = env => {
console.log(env)
env = env || {}
return Object.assign({
entry: './src/main.js',
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.vue$/,
use: 'vue-loader'
}
]
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue': 'vue/dist/vue.esm',
'@': path.join(__dirname, 'src')
}
}
}, modeOptions[env.mode])
}在src目录下新建App.vue文件,代码如下:const vueLoaderPlugin = require('vue-loader/lib/plugin')
// 省去了部分代码,相信大家都知道怎么写
new vueLoaderPlugin()修改main.js<template>
<div id="app">
<h1>{{title}}</h1>
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
title: 'Hello Vue'
}
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>import Vue from 'vue' // 设置了别名简写
import App from './App' // 省去了.vue
new Vue({
el: '#app',
template: `<App/>`,ue
components: {
App
}
})
接下来就是见证奇迹的时刻,运行npm run dev发现项目跑起来了,页面显示Hello Vue,修改title属性页面也会实时刷新,执行npm run build也没毛病。
后续补充
总算大功告成,先写到这里,本文完整代码在这里:传送门,后续还想继续完善参考webpack官方文档
基本上跟着敲下来实现了上面的步骤,再去用vue-cli创建一个项目去看他的配置文件就会很清晰了。
webpack主要两大核心,loader处理不认识的文件以及对内容进行统一处理,plugin扩展功能。再就是区分不同环境所需要用到的东西,把相同配置的放在base里面。
- 开发一般需要起本地服务、修改热更新、打包的js放在内存中的不需要配置输出路径、sourcemap来定位错误方便调试…
- 生产环境一般需要压缩、打包后的输出路径、tree shaking把没有引用到的模块给删除掉…
官方的脚手架是通过webpack-merge插件来合并配置项的,使用了webpack.DefinePlugin来设置环境变量。
开发配置中使用了webpack.NoEmitOnErrorsPlugin来屏蔽错误,避免代码出线错误中断本地服务。
生产配置中使用了webpack.HashedModulesPlugin保持module.id稳定,打包后的文件有一串hash值,假如模块没有改变hash值也不会变化浏览器就会从缓存中读取。
copy-webpack-plugin,拷贝指定的文件夹注入到打包结果中。像statci目录下的静态资源不打包就会用这个复制到dist目录下。
webpack.ProvidePlugin自动加载模块,比如很多页面都引用到某个第三方库,不必到处 import 或 require,统一设置变量就可以了,当这个变量在别的地方使用没有被赋值时就会自动加载第三方库。
webpack.DllPlugin提前处理第三方库的打包,我们一般第三方的包不会变,每次打包都会重新处理,设置dll就能优化打包速度。

