# vue-webpack-simple
**Repository Path**: taoyouyou/vue-webpack-simple
## Basic Information
- **Project Name**: vue-webpack-simple
- **Description**: 从零搭建一个基于webpack的vue开发环境
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 0
- **Created**: 2020-06-08
- **Last Updated**: 2024-04-05
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## 实例——从零创建一个vue应用
从零开始搭建一个简单的基于webpack的vue开发环境
本文安装的版本是vue2.0,webpack4.0版本。babel 7 版本
> 备注:当使用webpack4时,确保使用 Node.js的版本 >= 8.9.4。因为webpack4使用了很多JS新的语法,它们在新版本的 v8 里经过了优化。
### 一、 项目初始化——基础环境搭建
新建文件夹并初始化npm项目,生成package.json
```
mkdir vue-webpack-simple
cd vue-webpack-simple
npm init -y
```
安装vue webpack webpack-dev-server,注意webpack4需要单独安装webpack-cli,
```
npm i vue --save
npm i webpack webpack-dev-server --save-dev
npm i webpack-cli --save-dev
```
根目录下新建webpack.config.js,并先写入最基本的配置
```
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包
output: {
path: path.resolve(__dirname, './dist'), // 项目的打包文件路径
publicPath: '/dist/', // 通过devServer访问路径
filename: 'build.js' // 打包后的文件名
},
devServer: {
historyApiFallback: true, // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html。
overlay: true, // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖
}
};
```
### 二、引入vue(目前先不考虑单文件)
index.html,引入打包后的文件
```
Document
{{message}}
```
main.js
```
import Vue from 'vue';
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
});
```
修改webpack.config.js
```
var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
devServer: {
historyApiFallback: true,
overlay: true
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
}
};
```
此时整个项目目录结构如下所示

配置package.json,修改启动命令。
```
"scripts": {
"dev": "webpack-dev-server --open --hot",
"build": "webpack --progress --hide-modules"
},
```
注意:webpack-dev-server会自动启动一个静态资源web服务器 --hot参数表示启动热更新
可以发现浏览器自动打开的一个页面,页面打印 Hello vue,修改main.js输出的message值,只要保存一下,页面上就会自动刷新,非常方便。
#### 引入scss和css
webpack默认只支持js的模块化,如果需要把其他文件也当成模块引入,就需要相对应的loader解析器。
安装上scss相关插件
`npm i node-sass css-loader vue-style-loader sass-loader --save-dev`
node-sass 把 sass编译成css
sass-loader 是webpack的加载scss一个loader
鉴于国内的环境安装node-sass可能会失败,这个时候需要设置一下淘宝的镜像源。
webpack配置loader,webpack.config.js加入module
```
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}
]
}
```
还记得我们在上一文玩转webpack里讲的到,引入loader加载器的作用是告诉webpack编译器如下信息:
> 嘿,webpack编译器,当你在碰到「在 require()/import 语句中被解析为 '.css' 的路径」时,在你对它打包之前,先使用 分别用css-loader,vue-style-loader 去解析转换一下。”
注意:因为我们这里用vue开发,所以使用vue-style-loader,其他情况使用style-loader。
css-loader使得我们可以用模块化的写法引入css。
vue-style-loader会将引入的css插入到html页面里的style标签里。
同样方法可以配置scss
```
{
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
},
{
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
}]
```
我们现在来试下
在src目录下新建style目录,style目录里新建common.scss
```
body {
background: #fed;
}
```
main.js引入这个scss文件
`import './style/common.scss';`
发现css样式有用了
#### 使用babel转码
ES6的语法大多数浏览器依旧不支持,bable可以把ES6转码成ES5语法,这样我们就可以大胆的在项目中使用最新特性了。
babel转化语法所需依赖项:
- babel-loader: 负责 es6语法转化
- babel-core: babel核心包
- babel-preset-env:告诉babel使用哪种转码规则进行文件处理
在babel 7版本下把所有 babel-* 重命名为 @babel/*,所以需要安装对应的@babel/core @babel/preset-env包。
`npm install babel-loader @babel/core @babel/preset-env --save-dev`
在项目根目录新建一个.babelrc文件
```
{
"presets":["@babel/preset-env"]
}
```
webpack.config.js添加一个loader
```
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}
```
exclude表示忽略node_modules文件夹下的文件,不用转码。
现在我们来试下async await语法吧
src目录下新建util.js
```
export default function getData() {
return new Promise((resolve, reject) => {
resolve('ok');
})
}
```
main.js 引入这个方法
```
import getData from './util';
import Vue from 'vue';
import './style/common.scss';
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods: {
async fetchData() {
const data = await getData();
this.message = data;
}
},
created() {
this.fetchData();
}
});
```
这时控制台会报一个错误regeneratorRuntime is not defined,因为浏览器不支持新版本的api,而babel只转换新的js语法,不转换新的API。上面的设置能够在打包时把es6转为es5,但不包括es6的一些新特征,比如promise。
解决上面问题的方法是:
安装 @babel/polyfill:
`npm i @babel/polyfill --save-dev`
但是babel-polyfill 主要有两个缺点:
- 使用 babel-polyfill 会导致打出来的包非常大,很多其实没有用到,对资源来说是一种浪费。
- babel-polyfill 可能会污染全局变量,给很多类的原型链上都作了修改,这就有不可控的因素存在。
基于这种原因Babel7: 新增了 babel-preset-env,设置
> "useBuiltIns":"usage"这个参数值就可以实现按需加载 babel-polyfill 。
全局引入 babel-polyfill,这样打包后的整个文件体积必然是会变大,通过设置 "useBuiltIns":"usage"能够把 babel-polyfill 中你需要用到的部分提取出来,不需要的去除。
> useBuiltIns 参数说明:
> - false: 不对 polyfills 做任何操作
> - entry: 根据 target 中浏览器版本的支持,将 polyfills 拆分引入,仅引入有浏览器不支持的 polyfill
> - usage(新):检测代码中 ES6/7/8 等的使用情况,仅仅加载代码中用到的 polyfills
配置.babelrc,实现polyfills的按需加载。
```
{
"presets": [[
"@babel/preset-env",
{
"useBuiltIns": "usage"
}
]]
}
```
此时重新npm run dev,可以发现正常运行了
#### 引入图片资源
把图片也当成模块引入
`npm i file-loader --save-dev`
webpack.config.js添加一个loader
```
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
```
在src目录下新建一个img目录,存放一张图片logo.png
修改main.js
```
import url from './img/logo.png';
Vue.component('my-component', {
template: '
',
data() {
return {
url,
}
}
})
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue !'
},
methods: {
async fetchData() {
const data = await getData();
this.message = data;
}
},
created() {
this.fetchData()
}
});
```
修改index.html
```
Document
{{message}}
```
可以看见,图片也被正确加载了
### 三、单文件组件
在前面的例子里,我们使用 Vue.component 来定义全局组件
在实际项目里,更推荐使用单文件组件。
#### .vue 单文件组件 (SFC) 规范
.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 template、script 和 style,还允许添加可选的自定义块:
- template 模板块
一个SFC中最多一个< template >块;其内容将被提取为字符串传递给 vue-template-compiler ,然后 webpack 将其编译为 js 渲染函数,并最终注入到从script 导出的组件中;
- script 脚本块
一个SFC最多一个 script 块,会作为一个模块封装。它的默认导出应该是一个 Vue.js 的组件选项对象,也可以导出由 Vue.extend() 创建的扩展对象。
- style 样式块
一个 .vue 文件可以包含多个 style 标签,标签可以有 scoped 或者 module 属性。
- 自定义语言块
vue-loader 将会使用块名来查找对应的 loader 进行处理。
vue项目中使用vue-loader和vue-template-compiler来加载和就解析.vue。
安装vue-loader和vue-template-compile。
`npm i vue-loader vue-template-compiler --save-dev`
#### Webpack 配置 vue-loader
Vue Loader 的配置和其它的 loader 不太一样。除了通过 rules 规则将 vue-loader 应用到 .vue 的文件上之外,还需要添加 Vue Loader Plugin 插件:
```
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// ... 其它规则
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin()
]
}
```
Vue Loader Plugin 的职责是将 .vue 文件中的语言块应用在相应的 rules 上。例如样式匹配 .css的规则,那么它会应用到 .vue 文件里的 style 块,匹配 .js的规则会应用到 .vue 文件里的 script 块。
在src目录下新建一个App.vue
```
```
main.js
```
import Vue from 'vue';
import App from './App.vue';
import './style/common.scss';
new Vue({
el: '#app',
template: '',
components: { App }
})
```
index.html
```
Document
```
npm run dev,可以发现单文件被正确加载了。