从零开始搭Vue-cli

从零开始搭Vue项目,主要是想脱离对脚手架全家桶的依赖,以及从中深入学习一点webpack相关的知识,不要每次打开package.json以及webpack的配置文件都一脸懵逼。

新建项目

1
2
mkdir vue-cli-webpack
cd vue-cli-webpack

使用npm init生成package.json文件

1
npm init

执行上述命令后,在项目文件夹下生成了package.json文件。

文件中的各个字段介绍:package.json文件

引入webpack

webpack使用教程:webpack

1
2
npm install webpack --save-dev
npm install webpack-cli -D

然后创建一些必要的文件:

1
2
3
4
touch index.html
mkdir src
cd src
touch main.js

main.js文件如下:

1
console.log("hello world");

index.html文件如下:

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script src="dist/bundle.js"></script>
</body>
</html>

创建webpack.config.js文件

在项目目录下执行下面指令,懒的话直接gui创建就行了。

1
2
3
mkdir config
cd config
touch webpack.config.js

webpack.config.js文件内容如下:

一定要注意路径,不然很容易翻车车。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const path = require('path');
console.log(path.resolve(__dirname,'dist'))//F:\git_project\vue-cli-webpack\config\dist,因此使用'../dist'返回上一层,使生成的dist的路径为F:\git_project\vue-cli-webpack\dist

module.exports = {
//webpack4.0新增,可选择设置为development和production
mode:'development',
//口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
// 进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
entry:'../src/main.js',
//output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
// 基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。可以通过在配置中指定一个 output 字段,来配置这些处理过程
output:{
//path.resolve方法用于将相对路径转为绝对路径。
path:path.resolve(__dirname,'../dist'),
filename: "bundle.js"
}
}

使用webpack命令编译项目

需要在webpack.config.js文件所在的目录下执行下面的命令:

1
2
cd config
webpack

执行完毕后会在项目目录下生成dist文件夹(包括打包好的bundle.js文件)。此时项目目录结构如下:

image.png

此时用浏览器打开index.html文件,控制台打印如下:

image.png

引入vue

在项目目录下执行下面指令:

1
npm install vue

修改main.js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from 'vue';
let vm = new Vue({
el:'#app',
data:function () {
return{
msg:'hello vue'
}
},
template:'<p id="p-text">{{msg}}</p>',
created(){
console.log(this.msg);
}
})

引入babel

1
npm install --save-dev babel-core babel-loader

由于在使用vue时会用到很多es6的语法,但是现在很多浏览器对es6的支持不是很好,所以在编译时需要将这些语法转换es5的语法,此时我们使用babel来进行编译。

配置webpack.config.js

1
2
3
4
5
6
7
8
9
10
11
//loader 用于对模块的源代码进行转换。
module: {
rules: [
//配置babel-loader
{
test:'/\.js$/', //匹配js文件
loader: "babel-loader", //用于解析对应的文件
exclude:/node_modules/ //不包括node_module下的js文件
}
]
}

执行webpack命令重新打包,打开index.html,打印如下:

image.png

因为正在使用的是vue的运行时版本,而此版本中的编译器时不可用的,我们需要把它切换成运行时 + 编译的版本,需要在配置文件中添加如下代码 :

1
2
3
4
5
6
//这些选项能设置模块如何被解析。 
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
}

webpack一些常用配置

在项目的实际开发中我们还会引入css、图片以及字体等资源文件。这些文件的引入都需要相应的加载器才能将其加载到项目中并正常使用。

下面只介绍部分我们需要的加载器的使用方法, 更多信息请查阅webpack加载器文档

css加载器

1
npm install --save-dev css-loader style-loader

配置webpack.config.js的loader规则

1
2
3
4
5
//配置css-loader
{
test:/\.css$/,
loader: "style-loader!css-loader"
}

新增一个样式文件:

1
2
3
4
cd src
mkdir styles
cd styles
touch main.css

main.css如下:

1
2
3
4
5
#p-text{
width: 100%;
text-align: center;
color: red;
}

在main.js中引入main.css

1
import './styles/main.css'

重新编译程序,打开index.html如下:

image.png

配置图片资源加载器

使用file-loader或者url-loader加载器进行加载,他们都是用于打包文件和图片资源的,两者的区别是url-loader在file-loader的基础上进行了一次封装。

在访问网站时如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl(base64编码,优化方案之一)。相当于把图片数据翻译成一串字符,再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。

当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

此处我们使用url-loader,由于它是基于file-loader的封装,所以也需要引入file-loader。

1
npm install --save-dev file-loader url-loader

配置webpack.config.js:

1
2
3
4
5
6
7
8
//配置url-loader
{
test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
options: {
imit:10000//大于10kb不转码
}
}

接下来引入图片,修改main.js如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue';
import './styles/main.css'
import img from './img/snow.png'
let vm = new Vue({
el:'#app',
data:function () {
return{
msg:'hello vue',
img:img,
}
},
template:'<div><p id="p-text">{{msg}}</p><img style="display: block;width: 100%" :src="img"></div>',
created(){
console.log(this.msg);
}
})

重新打包编译,效果如下:

image.png

查看bundle.js文件,图片已经被转码:

image.png

image.png

字体加载

字体的加载方式与图片的一样也是用url-loader,配置如下 :

1
2
3
4
5
6
7
8
//配置字体
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000
}
}

HtmlWebpackPlugin 插件

这个插件用来简化创建服务于 webpack bundle 的 HTML 文件,尤其是对于在文件名中包含了 hash 值,而这个值在每次编译的时候都发生变化的情况。你既可以让这个插件来帮助你自动生成 HTML 文件,也可以使用 lodash 模板加载生成的 bundles,或者自己加载这些 bundles。

1
npm install --save-dev html-webpack-plugin

在webpack.config.js中配置插件:

1
2
3
4
5
6
7
//插件目的在于解决 loader 无法实现的其他事。
plugins:[
new HtmlWebpackPlugin({
title: 'vue-cli-webpack',
template: '../index.html'
})
]

删除index.html中的下面部分代码:

1
<script src="dist/bundle.js"></script>

在config目录下执行webpack重新打包编译,此时目录结构如下:

image.png

此时打开dist文件夹下的index.html,效果如下(本次图片大小大于10k):

image.png

webpack-dev-server

在我们实际开发中需要将代码部署在server中,而不是在浏览器中直接打开文件。此时我们需要使用webpack的 webpack-dev-server 。

webpack-dev-server 为我们提供了一个简单的web服务器,并且能够实时重新加载(live reloading)。

1
npm install --save-dev webpack-dev-server

在webpack.config.js 文件中需要指定一个文件夹,告诉开发服务器需要从哪儿加载文件:

1
2
3
4
//告知开发服务器需要从哪儿加载文件
devServer:{
contentBase:"./dist"
},

配置package.jsonscript脚本:

1
2
3
4
5
6
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//前面部分是执行的指令+参数,后面部分是执行的目录,也就是说在config/webpack.config.js目录下执行
"dev": "webpack-dev-server --open --inline --progress --config config/webpack.config.js",
"build": "webpack config/webpack.config.js"
},

重新修改webpack.config.js中的路径信息如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode:'development',
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'dist'),
filename: "bundle.js"
},
module: {
rules: [
{
test:'/\.js$/',
loader: "babel-loader",
exclude:/node_modules/
},
{
test:/\.css$/,
loader: "style-loader!css-loader"
},
{
test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: "url-loader",
options: {
limit:10000
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 'vue/dist/vue.common.js' for webpack 1
}
},
plugins:[
new HtmlWebpackPlugin({
title: 'vue-cli-webpack',
template: 'index.html'
})
],
devServer:{
contentBase:"./dist"
},
}

现在就可以愉快的执行下面的指令:

1
2
npm run dev
npm run build

vue-loader

在vue的开发过程中,通常我们需要写.vue结尾的文件即组件,如app.vue。需要通过vue-loader来进行加载,现在我们需要做如下配置。通过 vue-loader 和vue-template-compiler来加载并编译.vue文件。

1
npm install --save-dev vue-loader vue-template-compiler

Vue Loader 的配置和其它的 loader 不太一样。除了通过一条规则将 vue-loader 应用到所有扩展名为 .vue 的文件上之外,还要确保在webpack 配置中添加 Vue Loader 的插件

webpack.config.js 中

1
2
3
4
5
6
7
8
9
10
11
12
//loader
{
test: /\.vue$/,
loader: 'vue-loader'
}

//resolve
//自动解析确定的扩展。
extensions: ['.js','.vue'],

//plugins
new VueLoaderPlugin();

新建app.vue:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<p id="p-text">{{msg}}</p><img style="display: block;width: 100%" :src="img">
</div>
</template>
<script>
import img from '../img/night.png'
export default {
name: "app",
data:function () {
return{
msg:'hello vue',
img:img,
}
},
created(){
console.log(this.msg);
},
}
</script>
<style scoped>
</style>

修改main.js:

1
2
3
4
5
6
7
8
import Vue from 'vue';
import './styles/main.css'
import App from './component/app'
new Vue({
el:'#app',
template: '<App/>',
components: { App }
})

重新执行npm run dev,即可查看效果。

结束

到这里就差不多结束了。接下来就需要什么下什么,vue-router,vuex之类的。

整份代码请戳:vue-cli-webpack

还有推荐一个包分析工具:webpack-bundle-analyzer

Reference

webpack 搭建 vue 项目

webpack