5 Star 7 Fork 3

hwhao / webpack_vue_tutorials

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

[造轮子教程]十分钟搭建Webpack+Vue项目

本教程涉及技术栈和相关工具为:webpack@1,vue@1,vue-router@0.7,vuex@1,eslint

对于webpack@2和vue@2,请参考官方文档作改动

如果项目本身并没有特别需求,还是推荐使用vue-cli构建项目,方便快捷

推荐vue项目目录结构:

  • config 全局变量
  • dist 编译后的项目代码
  • src 项目源码
    • apis api封装
    • components Vue组件
    • libs js工具类
    • router 路由
      • index.js 路由对象
      • routes.js 路由配置
    • store Vuex的store
      • modules vuex模块
      • types.js type管理
    • styles css样式
    • views 页面组件
    • main.js vue入口文件
  • webpack.config Webpack各种环境的配置文件
  • package.json

第一步:初始化项目

  1. 所有项目的第一步当然是:创建项目文件夹,然后使用npm init -y创建package.json

  2. 项目根目录下建立srcdist文件夹,分别用来存放项目源码webpack编译后的代码

第二步:入口文件

  1. 根目录下直接建立一个index.html,作为页面的入口文件
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
</head>
<body>
  <div id="app">{{message}}</div>  <!-- Vue模板入口 -->
  <script src="dist/main.js"></script>
</body>
</html>
  1. src下建立一个main.js,作为Vue的入口文件
// import...from的语法是ES6的,需要用到babel,后面再说
// require的语法是Commonjs的,webpack已经实现了,可以直接使用
const Vue = require('vue')
new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue.js!'
  }
})
  1. 安装模块

安装Vue:npm install vue@1 --save 安装Webpack: npm install webpack --save-dev

  1. 使用webpack编译打包

除非在全局安装webpack,使用本地安装需要在package.jsonscript加入运行脚本,添加之后package.json如下:

{
  "name": "step2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack src/main.js dist/main.js"  // <---添加这句
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^1.0.28"
  },
  "devDependencies": {
    "webpack": "^1.14.0"
  }
}

运行npm run dev,再用浏览器打开index.html就能看到效果了:

Hello Vue.js!

第三步:编写webpack配置文件

上一步中直接使用webpack运行脚本webpack [入口文件] [出口文件],显然对于后期添加webpack插件和不同环境的配置是不行的。

  1. 在项目根目录下创建webpack.config文件夹专门用于存放webpack的配置文件

  2. 为了让配置文件不同的编译环境中能够复用(例如loaders的配置,不管在开发环境还是生产环境肯定都是一样的),在webpack.confg中首先创建一个base.js文件:

const path = require('path')
const root = path.resolve(__dirname, '..') // 项目的根目录绝对路径

module.exports = {
  entry: path.join(root, 'src/main.js'),  // 入口文件路径
  output: {
    path: path.join(root, 'dist'),  // 出口目录
    filename: 'main.js'  // 出口文件名
  }
}

上面这段配置就实现了webpack src/main.js dist/main.js的功能,还可以额外拓展一下,变成:

const path = require('path')
const root = path.resolve(__dirname, '..') // 项目的根目录绝对路径

module.exports = {
  entry: path.join(root, 'src/main.js'),  // 入口文件路径
  output: {
    path: path.join(root, 'dist'),  // 出口目录
    filename: 'main.js'  // 出口文件名
  },
  resolve: {
    alias: { // 配置目录别名
      // 在任意目录下require('components/example') 相当于require('项目根目录/src/components/example')
      components: path.join(root, 'src/components'),
      views: path.join(root, 'src/views'),
      styles: path.join(root, 'src/styles'),
      store: path.join(root, 'src/store')
    },
    extensions: ['', '.js', '.vue'], // 引用js和vue文件可以省略后缀名
    fallback: [path.join(root, 'node_modules')] // 找不到的模块会尝试在这个数组的目录里面再寻找
  },
  resolveLoader: {
    fallback: [path.join(root, 'node_modules')] // 找不到的loader模块会尝试在这个数组的目录里面再寻找
  },
  module: { // 配置loader
    loaders: [
      {test: /\.vue$/, loader: 'vue'}, // 所有.vue结尾的文件,使用vue-loader
      {test: /\.js$/, loader: 'babel', exclude: /node_modules/} // .js文件使用babel-loader,切记排除node_modules目录
    ]
  }
}

根目录下添加.babelrc用于配置babel

{
  "presets": ["es2015"]
}

使用了vue-loader和babel-loader需要安装包:

npm install --save-dev vue-loader@8 babel-loader babel-core babel-plugin-transform-runtime babel-preset-es2015 css-loader vue-style-loader vue-hot-reload-api@1 vue-html-loader

  1. webpack.confg创建dev.js文件:
const path = require('path')
const webpack = require('webpack')
const merge = require('webpack-merge')
const baseConfig = require('./base')
const root = path.resolve(__dirname, '..')

module.exports = merge(baseConfig, {})

上面的代码仅仅是导出了跟base.js一模一样的配置,下面我们添加更多用于dev(开发环境)的配置。

webpack-merge 用于合并两个配置文件,需要安装

npm install --save-dev webpack-merge

  1. 使用webpack dev server,开启一个小型服务器,不需要再手动打开index.html进行调试了

修改配置文件为:

module.exports = merge(baseConfig, {
  devServer: {
    historyApiFallback: true, // 404的页面会自动跳转到/页面
    inline: true, // 文件改变自动刷新页面
    progress: true, // 显示编译进度
    colors: true, // 使用颜色输出
    port: 3000, // 服务器端口
  },
  devtool: 'source-map' // 用于标记编译后的文件与编译前的文件对应位置,便于调试
})
  1. 添加热替换配置,每次改动文件不会再整个页面都刷新

安装webpack-dev-server:npm install --save-dev webpack-dev-server

module.exports = merge(baseConfig, {
  entry: [
    'webpack/hot/dev-server', // 热替换处理入口文件
    path.join(root, 'src/index.js')
  ],
  devServer: { /* 同上 */},
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 添加热替换插件
  ]
}
  1. 使用HtmlWebpackPlugin,实现js入口文件自动注入
module.exports = merge(baseConfig, {
  entry: [ /* 同上 */ ],
  devServer: { /* 同上 */ },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new HtmlWebpackPlugin({
      template: path.join(root, 'index.html'), // 模板文件
      inject: 'body' // js的script注入到body底部
    })
  ]
}

最后修改后完整的dev.js请查看源码

这里的HotModuleReplacementPluginwebpack内置的插件,不需要安装

HtmlWebpackPlugin需要自行安装:

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

在文件头中引入const HtmlWebpackPlugin = require('html-webpack-plugin')

修改index.html,去掉入口文件的引入:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
</head>
<body>
  <div id="app">{{message}}</div>  <!-- Vue模板入口 -->
  <!-- 去掉js入口文件 -->
</body>
</html>
  1. 最后修改package.json中的webpack运行脚本为:
{
  "dev": "webpack-dev-server --config webpack.config/dev.js"
}

为了测试webpack配置是否都生效了,下面创建一个vue组件src/components/Hello.vue

<template>
  <div>{{message}}</div>
</template>

<script>
  export default {
    data: () => ({message: 'Hello Vue.js!'})
  }
</script>

修改main.js

import Vue  from 'vue'
import Hello from './components/Hello.vue'

new Vue({
  el: '#app',
  template: '<div><hello></hello></div>',
  components: {Hello}
})

运行npm run dev,浏览器打开localhost:3000查看结果:

Hello Vue.js!

第四步:配置路由

  1. 安装vue-routernpm install --save vue-router@0.7

  2. 创建目录

src目录下创建views文件夹,用于存放页面组件 在src目录下创建router文件夹,用于存放所有路由相关的配置

  1. 添加路由页面

添加页面组件src/views/Home.vue

<template>
  <div><hello></hello></div>
</template>

<script>
  import Hello from 'components/Hello'
  export default {
    components: {Hello}
  }
</script>

添加src/router/routes.js文件,用于配置项目路由:

import Home from 'views/Home'

export default {
  '/': {
    name: 'home',
    component: Home
  }
}

添加路由入口文件src/router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import routes from './routes'

Vue.use(Router)

const router = new Router({
  hashbang: false,  // 关闭hash模式
  history: true,    // 开启html5history模式
  linkActiveClass: 'active' // v-link激活时添加的class,默认是`v-link-active`
})

router.map(routes)

router.beforeEach(({to, next}) => {
  console.log('---------> ' + to.name)  // 每次调整路由时打印,便于调试
  next()
})

export default router

修改main.js

import Vue  from 'vue'
import router from './router'

const App = Vue.extend({})

router.start(App, '#app')

最后别忘了编辑index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Demo</title>
</head>
<body>
  <div id="app">
    <router-view></router-view><!--路由替换位置-->
  </div>
</body>
</html>

重新执行npm run dev,浏览器打开localhost:3000查看效果

第五步:配置Vuex

vuex通常用于存放和管理不同组件中的共用状态,例如不同路由页面之间的公共数据

vuex中的几个概念:

state:状态,即数据

store:数据的集合,一个vuex引用,仅有一个store,包含n个state

mutation:state不能直接赋值,通过mutation定义最基本的操作

action:在action中调用一个或多个mutation

getter:state不能直接取值,使用getter返回需要的state

module:store和state之间的一层,便于大型项目管理,store包含多个module,module包含state、mutation和action

本教程中将以一个全局计数器作为例子

  1. 安装vuex

安装vuexnpm install --save vuex@1 添加src/store文件夹,存放vuex相关文件,添加src/store/modules用于vuex分模块管理

  1. 添加src/store/types.js,vuex的所有mutation type都放在一起,不建议分开多个文件,有效避免重名情况:
export const INCREASE = 'INCREASE' // 累加
export const RESET = 'RESET' // 清零
  1. 编写vuex模块,添加counter模块目录store/modules/counter

添加store/modules/counter/actions.js

import {INCREASE, RESET} from 'store/types'

export const increase = (({dispatch}) => {
  dispatch(INCREASE) // 调用type为INCREASE的mutation
})

export const reset = (({dispatch}) => {
  dispatch(RESET) // 调用type为RESET的mutation
})

添加store/modules/counter/index.js

import{INCREASE, RESET} from 'store/types.js'

const state = {
  count: 0
}

const mutations = {
  [INCREASE] (state) { state.count++ },
  [RESET] (state) { state.count = 0 }
}

export default {state, mutations}
  1. 添加store/index.js,作为vuex入口文件
import Vue from 'vue'
import Vuex from 'vuex'
import counter  from 'store/modules/counter'

Vue.use(Vuex) // 确保在new Vuex.Store()之前

export default new Vuex.Store({
  modules: {counter}
})
  1. 修改main.js,将store引入并添加到App中:
import Vue  from 'vue'
import router from './router'
import store from 'store'

const App = Vue.extend({store})

router.start(App, '#app')
  1. 最后改造一下src/components/Hello.vue,把action用上:
<template>
  <div>
    <p>{{message}}</p>
    <p>click count: {{count}}</p>
    <button @click="increase">increase</button><!--可以直接调用引入的action-->
    <button @click="reset">reset</button>
  </div>
</template>

<script>
  import {increase, reset} from 'store/modules/counter/actions' // 引入action
  export default {
    data: () => ({message: 'Hello Vue.js!'}),
    vuex: {
      actions: {increase, reset},
      getters: {
        count: ({counter}) => counter.count
      }
    }
  }
</script>

第六步:配置eslint

eslint不是必须的,但是强烈建议用在所有的javascript项目中

对于个人开发,可以在编程过程中发现并提示语法错误,有效过滤各种低级错误

对于团队开发,强制采用一致的编码风格,保证项目的统一性,有效避免各种任性行为

但是一定要注意,eslint定义的只是编码风格,规则是死的,人是活的,学会利用自定义规则的功能,增减规则

同时要知道,eslint检测不通过,不一定就是不能运行的,可能只是这种写法违背了编码风格,学会查看控制的查找具体错误原因

想要更好的eslint体验,请根据不同编辑器安装对应的eslint插件,主流的编辑器均已有相应插件

  1. 选择合适的编码风格

eslint提供了许多rules,可以直接在.eslintrc文件的rules中一个一个的配置

显然我们大多数情况下不需要这么做,网上已经有一些比较多人使用的风格了,本文推荐使用standard

  1. 配置.eslintrc文件

根目录下创建.eslintrc文件:

{
  "parser": "babel-eslint", // 支持babel
  "extends": "standard", // 使用eslint-config-standard的配置
  "plugins": [
    "html" // 支持.vue文件的检测
  ],
  "env": {
    "browser": true, // 不会将window上的全局变量判断为未定义的变量
    "es6": true // 支持es6的语法
  },
  "rules": { // 自定义个别规则写在这,0忽略,1警告,2报错
    "no-unused-vars": 1 // 将”未使用的变量“调整为警告级别,原为错误级别,更多规则请看官网
  }
}

结合不同编辑器的插件,打开js和vue文件中,就能看到提示了

根据使用的不同风格,安装所需的包,本文安装:

npm install --save-dev eslint babel-eslint eslint-config-standard eslint-plugin-standard eslint-plugin-html eslint-plugin-promise

第七步:webpack生产环境配置

前面已经配置过了开发环境下使用的配置文件dev.js,对于生产环境,通常需要对编译出来的文件进行压缩处理,提取公共模块等等,就需要专门提供一个配置文件

  1. 添加webpack.config/pro.js文件,把生产环境用不到的删掉,比如webpack-dev-serverwebpack-hot-replacement
const path = require('path')
const webpack = require('webpack')
const merge = require('webpack-merge')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const baseConfig = require('./base')
const root = path.resolve(__dirname, '..')

module.exports = merge(baseConfig, {
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(root, 'index.html'), // 模板文件
      inject: 'body' // js的script注入到body底部
    })
  ]
})

webpack常用插件:

extract-text-webpack-plugin 提取css到单独的文件

compression-webpack-plugin 压缩gzip

webpack.optimize.UglifyJsPlugin 压缩js文件,内置插件

webpack.DefinePlugin 定义全局变量,内置插件

webpack.optimize.CommonsChunkPlugin 提取公共依赖,内置插件

根据项目需求添加相应的插件,插件配置参数请查看官方文档,这里不进行罗列

  1. package.json中添加运行脚本:"build": "webpack --config webpack.config/pro.js"

  2. 运行npm run build,可以在dist文件夹中看到打包好的文件

“十分钟”只是噱头,多配几次,十分钟都不用。

轮子虽然都是圆的,也有轻重宽窄之分,造一辆车有时候也避免不了重造一个轮子。

空文件

简介

一步一步搭建webpack+vue项目。 展开 收起
JavaScript
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
JavaScript
1
https://gitee.com/hwhao/webpack_vue_tutorials.git
git@gitee.com:hwhao/webpack_vue_tutorials.git
hwhao
webpack_vue_tutorials
webpack_vue_tutorials
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891