由搭建Vue.js了解webpack,vue-loader和热重载

译文地址

Vue.js build set-up from scratch with webpack, vue-loader and hot reload

正文

Vue.JS 是我现在最喜欢的JavaScript视图库,在这篇文章中,我将向你解释如何使用Vue.JS、热模块修改、webpack以及整个vue生态系统建立一个项目,这样你就能更好的理解你的应用是如何工作的了。

介绍

从2007年至今,我已经使用JavaScript开发了很长时间,我喜欢angular,我喜欢react和ember,我能看到这些框架背后的动机和辉煌,但真正让我感到兴奋的框架是VueJS,他不是解决所有问题的完美方案,但我(以及很多人)看到了其中蕴含的价值。
在JavaScript中有一个整体趋势,尤其在react社区,让库专注于做好一件事,并允许用户将各种碎片以最好的方式粘在一起。这种方式很棒并且为大量的人服务,这对于初学者来说有一点压迫性。我受到了这篇文章的启发写下了这个教程,有大量的react模板在这-有些是过时的,有些有问题,而有些则无法工作,这些对于初学者而言都是痛苦的。
在写这篇文章的时候,Vue的开发者正在开发"官方入门套件",其中包含一个脚手架CLI来帮助构建一个新工程。这为开发带来了一个简单清晰而又可良好维护的出发点。
当然,搭建一个你自己的开发环境仍有很多好处:

  • 对比使用模板,你自己的工程依赖会更加顺手。
  • 如果有依赖不可用或你想要一些更新的东西,比如依赖一个预处理器或工具链,你可以直接将他引入而不会破坏构建流程。
  • 模板也许使用了某些你不需要的东西或库。

也就是说,模板和脚手架,尤其是那些发布的作者会更加了解库的价值,而你可以利用他们来学习并了解其原理,在你学习源码之后你就可以选择使用他们的模板。
请注意,在我写作的同时我也在不断学习一些新的东西,这篇文章我会经常更新。

在开始之前

我最后修改这些说明是在2015年12月28日,我已经在Ubuntu Linux上使用最新的稳定版Node.js(5.3)测试过。
在命令行运行命令如下所列

$ ls                           <- Run this in root directory of our project
$ (public/) ls                 <- Run this in the 'public' directory

第一部分:建立基础结构

让我们从一个空的文件夹开始建立一个名为"myapp"的工程,这将是未来所有说明的root文件夹

$ mkdir myapp
$ cd myapp/

在root文件夹建立一个package.json,至此我们还没有依赖。

{
  "name": "myapp",
  "version": "0.0.1",
  "description": "My app",
  "dependencies": {
  },
  "devDependencies": {
  },
  "author": "You"
}

在root文件夹建立一个index.html,这将是提供给浏览器的实际html。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Vue Example</title>
  </head>
  <body>
    <h3>{{ message }}</h3>
    <script src="dist/build.js"></script>
  </body>
</html>

注意关于这个html文件的两件事:

  1. 它使用了dist/build.js,而这一个JS文件还没有创建
  2. 他有一个{{ message }}片段,其数据将由vue在稍后填充

建立一个文件夹src并增加一个文件src/main.js

import Vue from 'vue'

new Vue({
  el: 'body',
  data: {
    message: "Hello Vue"
  }
})

至此我们已经有了基础vuejs应用的骨架,但他还需要构建完成。

第二部分:基础webpack构建

在你的root文件夹下新建一个文件名为webpack.config.js,在其中填充代码:

module.exports = {
  // 这是包含其他模块的主文件
  entry: './src/main.js',
  // 编译好的文件应该放哪?
  output: {
    // 路径在dist文件夹下
    path: './dist',
    // 文件名为`build.js`,因此完整的路径为dist/build.js
    filename: 'build.js'
  },
  module: {
    // 特殊编译规则
    loaders: [
      {
        // 请求webpack检查:如果文件以.js结尾,则应用转换
        test: /\.js$/,
        // 使用babel进行转换
        loader: 'babel',
        // 不转换node_modules文件夹(不需要编译)
        exclude: /node_modules/
      }
    ]
  }
}

在你的root文件夹下新建一个文件.babelrc,Babel是用于转换ES6到当前JavaScript版本的工具,它需要用presets配置,Vue依赖es2015preset(支持下一代EcmaScript/JavaScript)和stage-0(我不知道这是干嘛的[译者注:stage-0为ES7不同阶段语法提案的转码规则,此为第一阶段])

{
  "presets": ["es2015", "stage-0"],
  "plugins": ["transform-runtime"]
}

安装webpack命令行工具:

$ npm install -g webpack

安装本地库需要构建(如dev dependencies,开发依赖),我们可以将他增加到你的package.json的devDependencies部分。

    "babel-core": "^6.1.2",
    "babel-loader": "^6.1.0",
    "babel-plugin-transform-runtime": "^6.1.2",
    "babel-preset-es2015": "^6.1.2",
    "babel-preset-stage-0": "^6.1.2",
    "babel-runtime": "^5.8.0",
    "webpack": "^1.12.2",

在你完成package.json的更新后,执行:

$ npm install

注意:我建议使用官方Vue初始化套件以得到最好的支持版本,因为有时最新版本的依赖库并不会得到最好的支持。
最后,为你的主程序安装vuejs库,你需要将其放在dependencies中。

$ npm install --save vue

现在你可以使用WebPack构建你的应用,在你的root目录下执行:

$ webpack

你应该可以看到如下输出:

Hash: 6568e32467dc12c8aeeb
Version: webpack 1.12.9
Time: 743ms
   Asset    Size  Chunks             Chunk Names
build.js  246 kB       0  [emitted]  main
    + 3 hidden modules

在你的浏览器中打开index.html,如果你看到"Hello Vue",那么至此一切OK,恭喜你,你有了一个基础的VueJS工程。

第三部分:vue-loader和.vue文件

现在我们将要开始vuejs中很棒的一个部分:使用.vue文件创建组件。
如下更新你的index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Vue Example</title>
  </head>
  <body>
    <app></app>
    <script src="dist/build.js"></script>
  </body>
</html>

注意,对比在body节点中建立一个简单的视图模型(ViewModel),我们安装一个名为app的组件并架设在<app></app>中。
如下修改你的main.js

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

new Vue({
  el: 'body',
  components: { App }
})

现在,注意我们从app.vue文件中提取了一个名为App的新组件,并将其包含到body元素的实例中。
我们将创建一个名为src/app.vue的文件,将下列代码加入app.vue中:

<template>
<div class="message">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello from vue-loader!'
    }
  }
}
</script>

<style>
.message {
  color: blue;
}
</style>

在这个文件中:我们设置了一种样式,在script中定义了行为,并在template中定义了HTML模板。想要学习组件是如何工作的,你需要查看vuejs的文档。
现在我们重新执行webpack并且看看会发生什么:

Hash: c71cc00f645706203ac4
Version: webpack 1.12.9
Time: 749ms
   Asset    Size  Chunks             Chunk Names
build.js  246 kB       0  [emitted]  main
   [3] ./src/app.vue 0 bytes [built] [failed]
    + 3 hidden modules

ERROR in ./src/app.vue
Module parse failed: /home/anirudh/work/misc/vue-scaffold/example/src/app.vue Line 1: Unexpected token <
You may need an appropriate loader to handle this file type.
| <template>
| <div class="message">{{ msg }}</div>
| </template>
 @ ./src/main.js 7:11-31

Webpack不知道如何处理.vue文件,幸运的是这很容易修改解决,打开你的webpack配置,更新如下代码:

module.exports = {
  entry: './src/main.js',
  output: {
    path: './dist',
    publicPath: 'dist/',
    filename: 'build.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.vue$/,
        loader: 'vue'
      }
    ]
  },
  vue: {
    loaders: {
      js: 'babel'
    }
  }
}

现在,在你的package.jsondevDependencies部分增加如下项:

    "css-loader": "^0.23.0",
    "style-loader": "^0.13.0",
    "vue-loader": "^7.3.0",
    "vue-html-loader": "^1.0.0",

执行npm install来取得新的库

$ npm install

最后,再次执行webpack,你会看到如下输出:

Hash: 740a1d3c85161f03a0cf
Version: webpack 1.12.9
Time: 1355ms
   Asset    Size  Chunks             Chunk Names
build.js  258 kB       0  [emitted]  main
    + 11 hidden modules

如果你打开浏览器,你应该可以看到蓝色的"Hello from vue-loader",这就意味着样式、HTML和javascript都被正确编译。作为奖励给你一张Darcy的照片。


第四部分:热模块替换/热重载

热模块替换或热重载是JavaScript世界中最热的新技术,这允许你节约JavaScript文件并实时更新组件。
这是基础逻辑:

  • 你写了一个应用。
  • 你在浏览器中加载这个应用,并开始使用这个应用。
  • 这个应用有一个'state',Vue使用这个值来渲染页面。

如果你要做出改变或修复一个小bug,你需要重载这个页面,并重复所有步骤以使得应用回到初始state。
有了热重载,工程流程变得不同:

  • 打开应用,将其带入给定的state
  • 更新源码并保存
  • Webpack检查修改,他会只重新编译改变的模块
  • Webpack发送代码并使用如浏览器上的websockets改变在线应用
  • Vue使用新的模块并热重载你的代码,重新展示你的页面的同时保持state完整

第一步,我们需要使用WebPack的开发服务但不是在浏览器中以一个html文件打开它。首先,更新package.json中的devDependencies

    "vue-hot-reload-api": "^1.2.0",

如下执行:

$ npm install
$ npm install -g webpack-dev-server
$ webpack-dev-server --inline --hot

当你运行webpack-dev-server,你会看到一堆输出:

http://localhost:8080/
webpack result is served from /dist/
content is served from /home/anirudh/work/misc/vue-scaffold/example
Hash: ef5ed1df9062de968cb6
Version: webpack 1.12.9
Time: 1773ms
   Asset    Size  Chunks             Chunk Names
build.js  511 kB       0  [emitted]  main
chunk    {0} build.js (main) 465 kB [rendered]
    [0] multi main 52 bytes {0} [built]
    [2] (webpack)-dev-server/client?http://localhost:8080 2.48 kB {0} [built]
    [3] (webpack)/~/url/url.js 22.3 kB {0} [built]
    [... omitted for brevity ...]
   [85] ./~/vue-html-loader!./~/vue-loader/lib/selector.js?type=template&index=0!./src/app.vue 58 bytes {0} [built]
   [86] ./~/vue-hot-reload-api/index.js 5.62 kB {0} [built]
webpack: bundle is now VALID.

在浏览器中打开http://localhost:8080,你会看到同样的输出,但这还没有显示出Vue的HMR有多棒。改变你的src/app.vue:

<template>
<div class="message">Value is: {{ count }}</div>
<a href="#" @click="increment">Increment</a>
</template>

<script>
export default {
  data () {
    return {
      count: 0
    }
  },
  methods: {
    increment () {
      this.count ++;
    }
  }
}
</script>

<style>
</style>

重载http://localhost:8080,你会看到一个计数器,同时有一个按钮,点击这个按钮,计数器就会增加。
现在,更新代码,你可以改变样式、改变按钮名称甚至是increment功能改造,如果你保存了代码,组件便会更新。

后续内容

你的工程可能并不需要所有这些东西,但这是你应该知道的vue相关内容。在你开始构建应用前,有一些事情是需要你花点时间搜索和创建的:

区分开发/产品构建

对于产品,你需要一个分离的压缩版的构建,你可以看看vuejs的建议vue-loader-example webpack config
注意,将你的webpack.config移动到一个分离的文件夹需要你更多的配置。

测试

测试在本教程范围之外,并且你的测试策略依赖于你的应用本身,可以看 vue-loader-example test example是如何测试的。

使用图像,静态文件和CSS工作

如果你的应用需要传统的CSS文件和图像,webpack可以帮助你,使用file-loaderurl-loader等适当的加载器并提高开发流程。

注意

你可以通过eslint-loader配置eslintvue-loader-example是一个很好的例子,同时一个好的eslintrc可以很好的保障eslint的工作。

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

推荐阅读更多精彩内容

  • 来源:github.com Vue.js开源项目速查表:https://www.ctolib.com/cheats...
    zhangtaiwei阅读 11,523评论 1 159
  • 转载 :OpenDiggawesome-github-vue 是由OpenDigg整理并维护的Vue相关开源项目库...
    果汁密码阅读 22,985评论 8 125
  • 健康是指人在身体、心理、社会适应方面的良好状态。幼儿阶段是儿童身体发育和机能发展极为迅速的时期,也是形成安全感和乐...
    兮兮的小星星阅读 1,559评论 0 0
  • 如何建立一个安全的ubuntu server 参考DharanaSoftware的文章 Securing your...
    MMoooooon阅读 223评论 0 0
  • 文|鸣凤乔 生命在一点一点地变化,在你毫无知觉之中。当你恍然大悟的时候,才能掂出其的分量。 2017年10月27日...
    鸣凤乔阅读 2,535评论 146 98