找了很多 vue+webpack 构建的文章 感觉这个还是很不错的,简单易懂还有代码实例。
源码链接:http://git.oschina.net/hwhao/webpack_vue_tutorials
原文链接: https://github.com/varHarrie/Dawn-Blossoms/issues/7
提示: 代码没有敲错。完全可以搭好的! 感觉可以的给作者一个星。
推荐vue项目目录结构:
config 全局变量
dist 编译后的项目代码
src 项目源码
modules vuex模块
types.js type管理
index.js 路由对象
routes.js 路由配置
apis api封装
components Vue组件
libs js工具类
router 路由
store Vuex的store
styles css样式
views 页面组件
main.js vue入口文件
webpack.config Webpack各种环境的配置文件
package.json
第一步:初始化项目
所有项目的第一步当然是:创建项目文件夹,然后使用
npm init -y
创建package.json
项目根目录下建立
src
和dist
文件夹,分别用来存放项目源码
和webpack编译后的代码
第二步:入口文件
在
根目录
下直接建立一个index.html
,作为页面的入口文件
Demo `message`
在
src
下建立一个main.js
,作为Vue的入口文件
// import...from的语法是ES6的,需要用到babel,后面再说// require的语法是Commonjs的,webpack已经实现了,可以直接使用const Vue = require('vue')new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } })
安装模块
安装Vue:npm install vue@1 --save
安装Webpack: npm install webpack --save-dev
使用webpack编译打包
除非在全局安装webpack
,使用本地安装需要在package.json
的script
加入运行脚本,添加之后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插件和不同环境的配置是不行的。
在项目根目录下创建
webpack.config
文件夹专门用于存放webpack的配置文件为了让配置文件不同的编译环境中能够复用(例如
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
在
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
使用webpack dev server,开启一个小型服务器,不需要再手动打开
index.html
进行调试了
修改配置文件为:
module.exports = merge(baseConfig, { devServer: { historyApiFallback: true, // 404的页面会自动跳转到/页面 inline: true, // 文件改变自动刷新页面 progress: true, // 显示编译进度 colors: true, // 使用颜色输出 port: 3000, // 服务器端口 }, devtool: 'source-map' // 用于标记编译后的文件与编译前的文件对应位置,便于调试})
添加热替换配置,每次改动文件不会再整个页面都刷新
安装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() // 添加热替换插件 ] }
使用
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
请查看源码
这里的
HotModuleReplacementPlugin
是webpack
内置的插件,不需要安装但
HtmlWebpackPlugin
需要自行安装:npm install --save-dev html-webpack-plugin
在文件头中引入
const HtmlWebpackPlugin = require('html-webpack-plugin')
修改index.html
,去掉入口文件的引入:
Demo `message`
最后修改
package.json
中的webpack运行脚本为:
{ "dev": "webpack-dev-server --config webpack.config/dev.js"}
为了测试webpack配置是否都生效了,下面创建一个vue组件src/components/Hello.vue
:
`message`
修改main.js
:
import Vue from 'vue'import Hello from './components/Hello.vue'new Vue({ el: '#app', template: '', components: {Hello} })
运行npm run dev
,浏览器打开localhost:3000
查看结果:
Hello Vue.js!
第四步:配置路由
安装
vue-router
:npm install --save [email protected]
创建目录
在src
目录下创建views
文件夹,用于存放页面组件
在src
目录下创建router
文件夹,用于存放所有路由相关的配置
添加路由页面
添加页面组件src/views/Home.vue
:
添加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
:
Demo
重新执行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
本教程中将以一个全局计数器作为例子
安装vuex
安装vuex
:npm install --save vuex@1
添加src/store
文件夹,存放vuex相关文件,添加src/store/modules
用于vuex分模块管理
添加
src/store/types.js
,vuex的所有mutation type
都放在一起,不建议分开多个文件,有效避免重名情况:
export const INCREASE = 'INCREASE' // 累加export const RESET = 'RESET' // 清零
编写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}
添加
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} })
修改
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')
最后改造一下
src/components/Hello.vue
,把action用上:
`message`
click count: `count`
第六步:配置eslint
eslint不是必须的,但是强烈建议用在所有的javascript项目中
对于个人开发,可以在编程过程中发现并提示语法错误,有效过滤各种低级错误
对于团队开发,强制采用一致的编码风格,保证项目的统一性,有效避免各种任性行为
但是一定要注意,eslint定义的只是编码风格,规则是死的,人是活的,学会利用自定义规则的功能,增减规则
同时要知道,eslint检测不通过,不一定就是不能运行的,可能只是这种写法违背了编码风格,学会查看控制的查找具体错误原因
想要更好的eslint体验,请根据不同编辑器安装对应的eslint插件,主流的编辑器均已有相应插件
选择合适的编码风格
eslint提供了许多rules,可以直接在
.eslintrc
文件的rules
中一个一个的配置显然我们大多数情况下不需要这么做,网上已经有一些比较多人使用的风格了,本文推荐使用standard
配置
.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
,对于生产环境,通常需要对编译出来的文件进行压缩处理,提取公共模块等等,就需要专门提供一个配置文件
添加
webpack.config/pro.js
文件,把生产环境用不到的删掉,比如webpack-dev-server
、webpack-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 提取公共依赖,内置插件
根据项目需求添加相应的插件,插件配置参数请查看官方文档,这里不进行罗列
在
package.json
中添加运行脚本:"build": "webpack --config webpack.config/pro.js"
运行
npm run build
,可以在dist
文件夹中看到打包好的文件