快速到达:初始化项目 入口文件 webpack配置 配置路由 配置Vuex eslint webpack生产环境配置 常见错误总结 css
WebPack(前往官网)能够看作是模块打包机:直接分析项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。Gulp/Grunt是一种可以优化前端的开发流程的工具。html
Grunt和Gulp的工做方式是:在一个配置文件中,指明对某些文件进行编译,组合,压缩等任务的具体步骤,运行以后自动逐步完成设定的任务。
前端
而WebPack是一种模块化的方案,经过给定的主文件(如:index.js)使用不一样的loaders处理项目的全部依赖文件,最后打包为一个浏览器可识别的JavaScript文件。
vue
其实二者并不具有太多可比性,grunt/gulp 在配置上比较简单,环境搭建更容易实现;而webpack的处理速度更快更直接,能打包更多不一样类型的文件。html5
相关的技术:webpack@2,vue@1,vue-router@0.7,vuex@1 node
目录结构:
<ul>
<li>config全局变量
<li>dist编译后的项目代码</li>
<li>src项目代码
<ul> <li> apis api封装react
<li>components Vue组件 <li>libs js工具类 <li>router 路由 <li>index.js 路由对象 <li>routes.js 路由配置 <li>store Vuex的store <li>modules vuex模块 <li>types.js type管理 <li>styles css样式 <li>views 页面组件 <li>main.js vue入口文件</ul>
<li>webpack.config Webpack各类环境的配置文件
<li>package.json
</ul>webpack
1.建立项目文件夹, npm init -y
建立 package.json
git
2.项目根目录下创建src
和dist
文件夹,分别用来存放项目源码
和webpack编译后的代码
es6
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>
2.在src
下创建一个main.js
,做为Vue的入口文件
// require的语法是Commonjs的,webpack自身能够实现直接使用 // es6的语法须要依赖babel哦 const Vue = require('vue') new Vue({ el: '#app', data: { message: 'Hello Vue.js!' } })
3.安装模块: vue npm install vue@1 --save
; webpack npm install webpack --save-dev
(在本地安装)
本地安装的webpack 须要在package.json的 scripts 配置中添加运行脚本
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack src/main.js dist/main.js" // <---自行添加,指定运行的文件 **webpack [入口文件] [出口文件]** },
运行npm run dev
,再用浏览器打开index.html
就能看到效果了:
Hello Vue.js!
全局安装webpack npm install -g webpack
则无需指定脚本~
在上一步中专门指定了webpack运行脚本去运行指定的文件,但实际开发中,对于不一样环境的大型项目/系统开发显然是不知足的。所以建立一个文件专门存放webpack配置~
1.在根目录下建立 webpack.config
文件夹来存放webpack的配置文件;
2.在上面的目录下首先建立一个base.js
文件来存在一些公共环境下的配置文件(例如loaders的配置)
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”
webpack指定 入口文件 -> 出口文件 的功能了。
此外还能够拓展一下,使得兼容更多的功能~ (webpack@2 resolving)
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文件能够省略后缀名 (此处有坑坑坑==。)!!webpack@2+已经再也不要求强制转入一个空字符串 resolveLoader: { 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"] }
而.babelrc就是让 Babel 作你要它作的事情的配置文件。
babel-preset-es2015 打包了es6的特性
使用了vue-loader和babel-loader须要安装包: 运行以下命令(可能有坑哦,若踩可见文末 bug修复篇==。)
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
3.在 webpack.json
中建立 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一样的配置
其中 webpack-merge
用于合并两个配置文件,须要安装 => npm install --save-dev webpack-merge
4.自行搭建一个小型服务器,以避免手动调试 index.html 。定义使用 webpack dev server 。 (webpack@2 Proxy)
所以须要继续配置dev.js以下: 还有其余一切配置,可查阅 webpack-dev-server-cli
module.exports = merge(baseConfig, { devServer: { historyApiFallback: true, // 404的页面会自动跳转到/页面 inline: true, // 文件改变自动刷新页面 // progress: true, // 显示编译进度 !!有坑,待解决。下同~ 暂时不加这两个属性继续走下去吧~! // colors: true, // 使用颜色输出 port: 3800, // 服务器端口 !!注意不要被占用了哦 }, devtool: 'source-map' // 用于标记编译后的文件与编译前的文件对应位置,便于调试 })
5.添加热替换配置 HotModuleReplacementPlugin
,每次改动文件不会再整个页面都刷新。该配置是webpack内部插件,不须要安装。
module.exports = merge(baseConfig, { entry: [ 'webpack/hot/dev-server', // 热替换处理入口文件 path.join(root, 'src/index.js') ], devServer: { /* 同上 */}, plugins: [ new webpack.HotModuleReplacementPlugin() // 添加热替换插件 ] }
6.使用 HtmlWebpackPlugin
,实现js入口文件自动注入。npm install --save-dev html-webpack-plugin
,且须要在头部引入 => const HtmlWebpackPlugin = require('html-webpack-plugin')
(还在dev.js中哦)
module.exports = merge(baseConfig, { entry: [ /* 同上 */ ], devServer: { /* 同上 */ }, plugins: [ new webpack.HotModuleReplacementPlugin(), new HtmlWebpackPlugin({ template: path.join(root, 'index.html'), // 模板文件 inject: 'body' // js的script注入到body底部 }) ] }
7.修改index.html(根目录i 啊),去掉入口文件的引入:<script src="dist/main.js"></script>
8.修改package.json
的运行脚本:
{ "dev": "webpack-dev-server --config webpack.config/dev.js"//指向配置文件,而不是某一单一页面的js }
再来跑一下,检测是否webpack配置都成功运做了。建立一个vue组件 src/components/Hello.vue
<template> <div>{{message}}</div> </template> <script> export default { data: () => ({message: 'Hello Vue.js!'}) } </script>
相应的main.js也作出修改:
// import...from的语法是ES6的,因为已经安装了babel(可编译),故能够直接使用 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:3800
查看结果 Hello Vue.js! 而且改动页面会自动刷新,不须要再一遍遍command+r刷新啦。
1.安装 vue-router
: npm install --save vue-router@0.7
(固然了当下的vue + axois
会更搭哦)
2.src
下建立views文件夹
,用于存放页面组件;另外再建立router文件夹
,用于存放全部路由相关的配置
3.添加路由页面 src/views/Home.vue
:
<template> <div><hello></hello></div> </template> <script> import Hello from 'components/Hello' //引入已写vue组件 export default { components: {Hello} } </script>
4.添加 src/router/routes.js
文件,用于配置项目路由:
import Home from 'views/Home' export default { '/': { name: 'home', component: Home } }
5.添加路由入口文件 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
6.再次修改main.js
:
import Vue from 'vue' import router from './router' //直接导入路由配置 const App = Vue.extend({}) router.start(App, '#app')
7.最后别忘了index.html
:
<div id="app">{{message}}</div> <!-- 读取Vue,替换成? --> <router-view></router-view><!--路由替换位置-->
能够再次执行 npm run dev
: 浏览器直接访问 localhost:3800
查看效果。
(vuex)
专门为vue.js开发而配套的 状态管理模式 .一般用于存放和管理不一样组件中的共用状态,例如不一样路由页面之间的公共数据.
其余 几个概念:
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.安装 : npm install --save vuex@1
添加 src/store
文件夹,存放vuex相关文件,添加 src/store/modules
用于vuex分模块管理 ;
2.添加 src/store/types.js
,vuex的全部mutation type(操做类型)建议放在一块儿,有效避免重名状况:
export const INCREASE = 'INCREASE' // 累加 export const RESET = 'RESET' // 清零
3.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}
4.vuex入口文件: store/index.js
:
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} })
5.修改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')
6.改造一下 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定义的是编码风格,巧妙利用提供的rules,能够自定义配置 ,增减规则 ; 同时,在使用中检测不经过,不必定不能运行,只是违反了规则==。监督自我。
网上也已经有不少现有的配置了,建议(standard)
1.配置.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 // 将”未使用的变量“调整为警告级别,原为错误级别,更多规则请看官网 } }
用了啥就安装啥:npm install --save-dev eslint babel-esli nt eslint-config-standard eslint-plugin-standard eslint-plugin-html eslint-plugin-promis
1.添加webpack.config/pro.js
文件,相比dev.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底部 }) ] })
(经常使用插件) :
extract-text-webpack-plugin 提取css到单独的文件
compression-webpack-plugin 压缩gzip
webpack.optimize.UglifyJsPlugin 压缩js文件,内置插件
.....
2.在package.json
中添加运行脚本:"build": "webpack --config webpack.config/pro.js"
;
3.运行npm run build
,能够在dist
文件夹中看到打包好的文件~~
查问题shasum check failed
:
人话:npm镜像源错误。
解决:1.经过config命令
npm config set registry http://registry.cnpmjs.org npm info underscore
2.命令行指定
npm --registry http://registry.cnpmjs.org info underscore
以上两种均可以快速解决安装问题,但治标不治本,下次安装时仍会出现。所以推荐?,直接在配置中指定写死,一劳永逸~
3.编辑 ~/.npmrc
加入以下配置:
registry = http://registry.cnpmjs.org
解决:
一、首先安装n模块 npm install -g n
二、升级node.js到最新稳定版 n stable
若肯定在最新版本中仍是在报错的话,则须要检查是否时webpack.config中配置有错误,webpack@1.xx->webpack@2.xx 各中的(升级特性) 仍是很重要的
sudo n latest
后升级过慢,中间不够稳定,直接强行被退出。以后再运行,关于npm 和node 的全部命令均在报segmentation fault 11这个错误。觉得os被玩坏了,系统错乱,吓死宝宝了==。
缘由:执行n命令,显示当前没有选中任何版本。 解决:用n命令从新设置要使用的版本 sudo n 版本号
解决:执行npm install --save-dev eslint-plugin-import@^2.0.0
npm install --save-dev eslint-plugin-node@4.2.2
完。感谢阅读,不足之处欢迎指出~thx!
wendy.wenxia@foxmail.com 2017/05/18