快速构建 vue 编码环境

一、用 vue-cli 克隆一个官方的模板

安装vue-cli组件

cnpm install -g vue-cli

创建一个官方的模板项目。

vue init webpack-simple vue-demo
cd vue-demo
cnpm install 

二、安装组件

# 常用的loaders
cnpm install --save-dev json-loader
cnpm install --save-dev css-loader style-loader postcss-loader autoprefixer
cnpm install --save-dev image-webpack-loader url-loader file-loader

# js/jsx 处理平台
cnpm install --save-dev babel-core babel-loader babel-register babel-plugin-transform-runtime babel-runtime babel-plugin-component
cnpm install --save-dev babel-preset-es2015 babel-preset-stage-0 babel-preset-stage-2

# eslint 环境
cnpm install --save-dev eslint-loader babel-eslint
cnpm install --save-dev eslint-config-vue eslint-config-standard vue-template-compiler eslint-friendly-formatter
cnpm install --save-dev eslint eslint-plugin-vue eslint-plugin-flow-vars eslint-plugin-promise eslint-plugin-standard eslint-plugin-html

# vue 组件
cnpm install --save vue
cnpm install --save-dev vue-loader vue-html-loader vue-style-loader vue-template-compiler

# webpack
cnpm install --save-dev cross-env@beta webpack@beta webpack-dev-server@beta
cnpm install -g cross-env@beta webpack@beta webpack-dev-server@beta
cnpm install --save-dev html-webpack-plugin copy-webpack-plugin clean-webpack-plugin # HTML模板插件/文件复制插件/目录清理插件
cnpm install --save-dev extract-text-webpack-plugin@beta # 分离css插件

三、编辑配置文件

3.1 编辑 webpack.config.js

var path = require('path') // `output.path`必须是一个绝对路径
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin') // 分离css文件的插件
// var CopyWebpackPlugin = require('copy-webpack-plugin')  // 复制文件和目录的插件
var CleanWebpackPlugin = require('clean-webpack-plugin') // 清理dist目录插件

// webpack.base.config 基本配置
module.exports = {
  entry: ['./src/main.js'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.[hash].js'
  },
  module: {
    rules: [
      {test: /\.json$/i, loader: 'json-loader'},
      {test: /\.(css|sass|less|scss)$/i, loader: ExtractTextPlugin.extract({fallbackLoader: 'style-loader', loader: 'css-loader?modules!postcss-loader'})},
      {test: /\.vue$/i, loader: 'vue-loader'},
      {test: /\.js?$/i, loader: 'babel-loader', exclude: /node_modules/}, // .js .jsx 文件通过label平台处理,配置文件.babelrc
      {test: /\.(woff|eot|ttf)$/i, loader: 'url-loader', query: {limit: 8192, name: 'fonts/[name].[ext]?[hash]'}},
      // 先通过 image-webpack-loader 将图片进行优化,
      // 然后由url-loader处理,当图片大小小于8k时,将图片转换为base64字节,当图片大于8k时输出到 imgs/[hash].[ext]
      {test: /\.(png|jp?g|gif|svg)$/i, loaders: [{loader: 'url-loader', query: {limit: 8192, name: 'imgs/[hash].[ext]'}}, {loader: 'image-webpack-loader', query: {progressive: true, optimizationLevel: 8, interlaced: false, pngquant: {quality: '70-90', speed: 4}}}]}
    ]
  },

  resolve: { // 请求重定向,应用于 `require` 语句
    alias: {'vue$': 'vue/dist/vue.common.js'} // 使用别名进行重定向,它和扩展名(externals)重定向不能同时使用。
  },

  plugins: [
    new webpack.LoaderOptionsPlugin({options: {
      postcss: function () { return [require('autoprefixer'), require('precss')] }
    }}),
    new webpack.NoErrorsPlugin(), // 允许错误不打断程序
    new ExtractTextPlugin('style.css?[hash]'), // 分离的 css 输出文件名
    // new CopyWebpackPlugin([{from: './src/public', to: 'public'}]), // 复制公共文件
    new HtmlWebpackPlugin({template: './src/main.tpl', filename: 'index.html', inject: 'body', minify: {removeComments: true, collapseWhitespace: true}}) // HTML模板
  ]
}

// webpack.dev.config 开发环境配置
if (process.env.NODE_ENV === 'development') {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.HotModuleReplacementPlugin() // 全局开启代码热替换
  ])
  module.exports.devServer = { // 本地服务器配置
    port: 8080,
    host: 'localhost',
    historyApiFallback: true,
    noInfo: true,
    contentBase: './dist' // 目录
  }
  module.exports.devtool = 'cheap-module-eval-source-map' // sourceMap 选项,用于调试和定位
};

// webpack.prod.config.js 项目打包配置
if (process.env.NODE_ENV === 'production') {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({'process.env': {NODE_ENV: '"production"'}}),
    new CleanWebpackPlugin(['./dist'], {verbose: true, dry: false, exclude: []}), // 打包前先删除 dist 目录
    // new webpack.optimize.CommonsChunkPlugin('commons.[hash].js'),  //提取公用函数
    new webpack.optimize.UglifyJsPlugin({sourceMap: true, compress: {warnings: false}}), // 压缩打包的文件,但不包括js文件。ps: js文件通过 `webpack -p` 压缩
    new webpack.BannerPlugin('Written by Bing.Rowe, Compiled at ' + new Date().toLocaleString()) // 给文件添加编译时间
  ])
  module.exports.devtool = 'cheap-module-source-map'
}

3.2 ESLint 配置文件

创建 .eslintignore,表明 eslint 检测时,要忽略掉这些目录。

build/*
dist/*
node_modules/*

eslint配置文件 .eslintrc.js

module.exports = {
  root: true,
  parser: 'babel-eslint',
  parserOptions: {
    sourceType: 'module'
  },
  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
  extends: ['standard'],
  // required to lint *.vue files
  plugins: ['vue', 'html'],
  // add your custom rules here
  'rules': {
    // allow paren-less arrow functions
    'arrow-parens': 0,
    // allow async-await
    'generator-star-spacing': 0,
    // allow debugger during development
    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
  }
}

3.3 js,jsx文件处理平台 babel 的配置文件 .babelrc

{
  "presets": ["es2015", "stage-0", "stage-2"],
  "comments": false,
  "env": {
    "production": {
      "plugins": [
        ["transform-runtime", { "polyfill": false, "regenerator": false }]
      ]
    }
  }
}

3.4 编辑 package.json

{
  "name": "vue-demo",
  "description": "A Vue.js project",
  "version": "1.0.0",
  "author": "Bing.Rowe <bing.rowe@foxmail.com>",
  "private": true,
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --inline --hot",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "lint": "eslint --ext .js,.vue src"
  },
  "dependencies": {
    "vue": "^2.1.4"
  },
  "devDependencies": {
    "autoprefixer": "^6.5.3",
    "babel-core": "^6.18.2",
    "babel-eslint": "^7.1.1",
    "babel-loader": "^6.2.8",
    "babel-plugin-component": "^0.6.0",
    "babel-plugin-transform-runtime": "^6.15.0",
    "babel-preset-es2015": "^6.18.0",
    "babel-preset-stage-0": "^6.16.0",
    "babel-preset-stage-2": "^6.18.0",
    "babel-register": "^6.18.0",
    "babel-runtime": "^6.18.0",
    "clean-webpack-plugin": "^0.1.14",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^3.1.3",
    "css-loader": "^0.26.0",
    "eslint": "^3.11.1",
    "eslint-config-standard": "^6.2.1",
    "eslint-config-vue": "^2.0.1",
    "eslint-friendly-formatter": "^2.0.6",
    "eslint-loader": "^1.6.1",
    "eslint-plugin-flow-vars": "^0.5.0",
    "eslint-plugin-html": "^1.7.0",
    "eslint-plugin-promise": "^3.4.0",
    "eslint-plugin-standard": "^2.0.1",
    "eslint-plugin-vue": "^1.0.0",
    "extract-text-webpack-plugin": "^2.0.0-beta.4",
    "file-loader": "^0.9.0",
    "html-webpack-plugin": "^2.24.1",
    "image-webpack-loader": "^3.0.0",
    "json-loader": "^0.5.4",
    "postcss-loader": "^1.1.1",
    "style-loader": "^0.13.1",
    "url-loader": "^0.5.7",
    "vue-html-loader": "^1.2.3",
    "vue-loader": "^10.0.2",
    "vue-style-loader": "^1.0.0",
    "vue-template-compiler": "^2.1.4",
    "webpack": "^2.1.0-beta.27",
    "webpack-dev-server": "^2.1.0-beta.12"
  }
}
  • npm run dev 启动本地服务器,运行项目
  • npm run build 打包项目,输出到dist目录
  • npm run lint 代码检查

3.5 .gitignore

.DS_Store
node_modules/
dist/
npm-debug.log

3.6 使用EditorConfig来规范缩进风格,缩进大小,tab长度以及字符集等

很多开发工具中都可找到editconfig的插件,在项目的根目录创建 .editorconfig

root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

四、写代码

目录结构

|   App.vue
|   main.js
|   main.tpl
\---assets
        logo.png

4.1 HTML模板文件 ./src/main.tpl

<!DOCTYPE html>
<html lang="zh">
  <head>
    <meta charset="utf-8">
    <title>DEMO</title>
  </head>
  <body><div id="app"></div></body>
</html>

4.2 入口文件 main.js

import Vue from 'vue'
import App from './App.vue'

/* eslint-disable no-new */
new Vue({
  el: '#app',
  render: h => h(App)
})

4.3 App.vue

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
      <li><a href="https://gitter.im/vuejs/vue" target="_blank">Gitter Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

h1, h2 {
  font-weight: normal;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

npm run dev 查看演示页面吧。

<END>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,302评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,232评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,337评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,977评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,920评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,194评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,638评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,319评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,455评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,379评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,426评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,106评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,696评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,786评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,996评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,467评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,043评论 2 341

推荐阅读更多精彩内容