[转] Vue + Webpack 组件式开发(练习环境)
前言
研究了下别人的 vue
多页面框架, 都是直接复制 package.json
文件,然后在本地 npm install
一下即可, 或者使用官网 vue-cli
工具生成一个项目, 觉得这样虽然看的懂, 但是记不住, 因此有必要从零开始搭建一个使用 .vue
作为组件的项目练习一下, 因此有了这个项目.
既然使用了 .vue
组件, 就不能像之前使用 jQuery
一样把 vue.js
引入页面中, 而是使用配套的 webpack
+ babel
+ 各种 loader
工具编译 .vue
文件, 再打包生成 html
.
FBI warning
切记
: 因为是最基本的初体验, 所以一些正式开发中必装的 loader
和 plugin
就没有装, 因为只是想按照官方教程手动敲出来加深印象, 特别是进阶教程中比较麻烦的父子组件传参, 作用域插槽, 递归组件以及 slot
等. 因此这个配置不可能作为正式开发的参照配置, 只可作为了解 vue
组件工作原理的练手项目.
配置说明
以下配置的详细说明在后面可以找到, 不想看的话直接复制下面的 package.json
即可, 但是为了加深印象还是建议手动敲一遍.
废话不多说, 开始.
首先, 既然是 webpack+vue
, 那相应的安装包少不了, 这里我们使用 vue@2.2.4
和 webpack@1.12.2
:
npm install webpack@1.12.2 vue@2.2.4 --save-dev
然后是 babel
和相应的 loader
, 这里我们使用 es2015
这个配置, 用最新的就好:
npm install babel bebel-core babel-loader babel-preset-es2015 --save-dev
然后是 webpack
的必装 loader
, css-loader
用来处理 css
中 url()
的资源, style-loader
用来将 require
的 css
抽出放到 style
标签中, 然后加到页面 head
部分. html-webpack-plugin
用来将入口文件 js
变成 html
, 入口文件中的各种资源由各种 loader
处理后插入到它生成的 html
中, extract-text-webpack-plugin
用来将被 js
通过 style
标签 append
到 head
中的样式抽出到单独的 .css
文件中:
npm install css-loader style-loader html-webpack-plugin extract-text-webpack-plugin@1.0.1 --save-dev
然后是 vue
相关的东西, 因为一个 .vue
里面有至少有三个标签 template/style/script
, 因此需要三个 loader
来处理, 再加上一个总的 vue-loader
, 就是四个 loader
,这里:
vue-html-loader
是 webpack
的官方 html-loader
的 fork
, 作者放到这里只是为了能在 webpack.config.js
中的 module.export.vue
对象上使用 html
选项来单独配置 vue
的 相关 html
(本项目安装 vue-loader
即可, 这里只是顺带安装说明一下);
vue-style-loader
用来处理 .vue
文件中 style
中的内容, 是 webpack
的官方 style-loader
的 fork
(本项目安装 vue-loader
即可, 这里只是顺带安装说明一下);
vue-template-compiler
用来处理 .vue
文件中 template
中的内容, 除非是用它编译后的文件做其他事情才需要单独配置(即写 build tools
, 否则这个不是必须的, 因为 vue-loader
已经默认使用它了)(本项目安装 vue-loader 即可, 这里只是顺带安装说明一下);
vue-loader
用来处理 .vue
后缀的内容, 在遇到相关的内容时, 会调用上述三个相关的 loader
来处理.
npm install vue-html-loader vue-loader vue-style-loader vue-template-compiler --save-dev
最后就是开发用的 webpack-dev-server
, 这里我们安装 1.12.1
版本:
npm install webpack-dev-server --save-dev
下面是总的 package.json
配置文件, 而具体的每个 package.json
字段的含义, 可以查看这个网站,
{ "name": "vue-components", "version": "0.0.1", "description": "vue components test", "main": "app/app.js","scripts": { "dev": "webpack-dev-server --hot", "build": "webpack" }, "keywords": [ "vue", "components" ],"author": "xheldon", "license": "MIT", "dependencies": { "vue": "^2.2.4" }, "devDependencies": { "babel":"^6.23.0", "babel-core": "^6.24.0", "babel-loader": "^6.4.1", "babel-preset-es2015": "^6.24.0", "css-loader":"^0.27.3", "extract-text-webpack-plugin": "^1.0.1", "html-webpack-plugin": "^2.28.0", "style-loader":"^0.16.0", "vue-html-loader": "^1.2.4", "vue-loader": "^11.3.1", "vue-style-loader": "^2.0.4", "vue-template-compiler": "^2.2.4", "webpack": "^1.12.2", "webpack-dev-server": "^1.12.1" } }
项目说明
Ok, 依赖安装完了, 接下来看下 webpack
配置, 因为是想尽快测试 vue
官方文档的组件部分, 所以一切从简了:
var path = require('path'); var webpack = require('webpack'); var HtmlwebpackPlugin = require('html-webpack-plugin'); // 常用配置,项目较小不抽出了 var ROOT_PATH = path.resolve(__dirname);//根路径 var APP_PATH =path.resolve(ROOT_PATH, 'app');//开发路径 var BUILD_PATH = path.resolve(ROOT_PATH, 'build');//输出路径 varExtractTextPlugin= require('extract-text-webpack-plugin'); module.exports = { entry: { app:path.resolve(APP_PATH, 'app.js') }, output: { path: BUILD_PATH, filename: 'bundle.js'//因为只有一个入口文件, 因此直接写死了 }, resolve: { alias: { //注意, 这里导入的是/node_module/vue/dist/vue.js, 跟 vue-router.js 的不同vue: 'vue/dist/vue.js' } }, //开启 dev source map devtool: 'eval-source-map', //开启 dev server devServer: {historyApiFallback: true, hot: true,//HMR inline: true, progress: true }, module: { loaders:[ { test:/\.vue$/, loader: 'vue' }, { test: /\.css$/, loader: ExtractTextPlugin.extract('css-loader') }, { test:/\.js$/, loader: 'babel', include: ROOT_PATH, exclude: /node_modules/ }, { test: /\.html$/, loader: 'vue-html'} ] }, vue:{ loaders: { css: ExtractTextPlugin.extract('css-loader') } }, plugins:[ new HtmlwebpackPlugin({title: 'Vue component test', filename: 'this_is_final_filename_address_you_visit_in_browser.html',//生成的最终文件名 template: 'app/this_is_main_page_which_you_put_components_into.html',//放置组件的地方, 一般是一个 body 下一个孤零零的 app 标签即可. inject: true }) ] };
关于这个配置, 有点东西需要说一下.
从上往下, 首先是 alias
, 使用过 vue-router
的人可能不需要这个配置, 但是使用 .vue
组件的项目必须这个配置,因为需要指定使用的 vue
的 js
类型, 看下本项目下 node_module/vue/dist/
文件夹下的文件, 有 vue.js
和 vue.common.js
两种, 其中 vue
编译 template
组件的时候是需要一个 compiler.js
的, 目的是把 template
中的 html
内容编译成 render
函数:
编译前:
<div id="app"> Hello </div> <script> new Vue({ el: '#app', data: {who: 'Vue'} }) </script>
编译后:
<div id="app"></div> <script> new Vue({ el: '#app', render: function () { with (this) { __h__('div',{staticAttrs:{"id":"app"}}, [("\n Hello "+__toString__(who)+"\n")], '' ) } }, data: {who: 'Vue'} }) </script>
而 vue
使用 compiler
编译 template
后的 js
在运行的时候发现有 render
函数的话就直接执行 render
, template
字段下的内容会被忽略. 而执行编译后的 render
的任务,是由 vue.common.js
完成的.因此:
vue.js = vue.common.js + compiler.js
所以, 如果你使用的是 vue-router
, 它的 package.json
中的 main
字段是指向 node_module/dist/vue.common.js
的, 如果你直接复制这个到你的项目下, 运行的时候会提示你类似于 vue.common.js
的 runtime
错误之类的信息.
其次需要说的是这个 css-loader
和 style-loader
以及 vue-style-loader
, 有了 style-loader
为何还要个 vue-style-loader
呢? 看了下 vue-style-loader
的说明, 明白了其仅仅是一个 style-loader
的 fork
, 但是为了单独处理 .vue
文件, 同时为了让用户配置 vue
更清晰, 将其加到了 webpack@1.x
的配置文件中的 vue
字段中. 可以通过将 extract-text-webpack-plugin
插件的配置从:
vue:{ loaders: { css: ExtractTextPlugin.extract('vue-style-loader','css-loader') } }
改成:
vue:{ loaders: { css: ExtractTextPlugin.extract('style-loader','css-loader') } }
发现编译后的结果一样证实.
而默认情况下, vue-loader
是自动使用 vue-style-loader
的, 所以如果你不在 .vue
文件中 @import
任何 css
, 那么你不需要手动把 vue-loader-style
放到 vue.loaders
字段中. vue-loader
会自动处理 .vue
文件中的 style
标签中的内容, 并将其放到 style
标签中插入页面. 而如果你需要在 .vue
文件中的 style
标签内 @import css
文件, 那么你就需要在 module.exports.vue
单独配置.可以通过把 vue
字段的 vue-style-loader
去掉来测试:
module: { loaders:[ { test: /\.vue$/, loader: 'vue' } ] }, vue:{ // loaders: { // css: 'vue-style-loader!css-loader' // } }
此外, 入口文件 js
中的 require('xxx.css')
是默认的 module.exports.module.loader
处理的, 这点可以通过在默认 loader
中使用 extract
插件, 而在 module.exports.vue
中不使用 extract
插件证实, 因为从结果可以发现, 入口文件中的 css
被提取了, 但是 .vue
中的 @import
来的 css
没有被提取.
而如果你需要 将入口文件中 require
来的 css
文件单独提取出来, 那么你就需要在 module.exports.module.loader
设置 extract-text-webpack-plugin
了.
注意: vue-style-loader
放在 module.exports.vue.loaders
字段中是为了能提取出 .vue
文件中的 style
标签内容到一个单独的 .css
文件 link
在页面中, 把 style-loader
和 css-loader
放在默认的 module.exports.module.loaders
中, 对处理 vue
中的 style
标签内容无效————起码在 Vue 1.x
版本和 webpack 1.x
版本无效, webpack 2.x
版本移除了第三方的字段, 限制在 module.export
中随意添加字段.
最后, css-loader
和 style-loader
总是写在一起的, 因为 css-loader
的作用是 resolve css
文件中的 @import
和 属性值 url()
中的依赖关系, 单独写其实是没什么用的. style-loader
才是处理 css
, 并将其打包到 js
中, 最后以 <style>
标签的形式插入到 head
(插入位置可配置)中的 loader
.
最后讲讲 extract-text-webpack-plugin
, 其接受三个参数:
第一个参数是可选参数, 传入一个 loader
, 当 css
样式没有被抽取的时候可以使用该 loader
. 第二个参数则是用于编译解析的 css
文件 loader
, 很明显这个是必须传入的, 就像上述例子的 css-loader
. 第三个参数是一些额外的备选项, 貌似目前只有传入 publicPath
, 用于当前 loader
的路径.
那什么时候需要传入第一个参数呢,那就得明白什么时候样式不会被抽取出来. 了解过 code splitting
的同学便会知道,我们有些代码在加载页面的时候不会被使用时, 使用 code splitting
, 可以实现将这部分不会使用的代码分离出去, 独立成一个单独的文件,实现按需加载.
那么如果在这些分离出去的代码中如果有使用 require
引入样式文件, 那么使用 ExtractTextPlugin
这部分样式代码是不会被抽取出来的. 这部分不会抽取出来的代码, 可以使用 loader
做一些处理, 这就是 ExtractTextPlugin.extract
第一个参数的作用.
OK, 聊完了配置文件, 再说说这个项目是怎么工作的.
一图胜千言, 上图, 首先是代码界面:
(若图片显示较小请在右键在新标签页单独查看)
看箭头所示就明白啦, 首先一个页面是至少有一个组件的, 这个我直接就一个页面一个组件来写了, 没有 import
其他的组件.
因此, 一个页面下是至少三个文件的, .vue
文件, .js
入口文件, 和 .html
, 组件插入的文件.
html
中写一个组件 app
的名字, 入口文件实例化一个 vue
, 然后使用 app
这个组件, 同时这个叫做 app
组件的模板来自 index.vue
, 组件对应的 css
和 js
以及 mvvm
的特色:数据绑定也写在 index.vue
里面.
有同学会疑惑, 入口文件 js
是怎么找到同目录的 html
文件的呢? 其实这个在 webpack.config.js
配置文件就已经写好了:
plugins:[ new HtmlwebpackPlugin({ title: 'Vue component test', filename:'this_is_final_filename_address_you_visit_in_browser.html',//生成的最终文件名 template:'app/this_is_main_page_which_you_put_components_into.html',//放置组件的地方, 一般是一个 body 下一个孤零零的 app 标签即可. inject: true }) ]
这个 html
生成的插件告诉 js
入口文件, 所需要的模板来自 app
下的 xxx.html
, 而最后打包的 bundle.js
也是 inject
这个里面, 再生成最终的页面.
还有同学会问, 在入口 js
文件中, vue
实例化的时候用到的 components.App
到底是在编译过程就找到了 this_is_main_page_which_you_put_components_into.html
文件中的 <app>
组件引用, 还是在 runtime
的时候, 从最终打包的 bundle.js
中运行, 然后寻找 this_is_final_filename_address_you_visit_in_browser.html
页面中的 <app>
标签呢? 答案是后者, 因为刚才说的 HtmlwebpackPlugin
插件只负责生成 html
和注入打包后的 bundle.js
, 而 vue
被打包进了 bundle.js
之后实例化 vue
时候才会寻找 <app>
标签.
这么一看, 和直接在 script
标签中引用 vue.js
文件再渲染的效果是一样的, 只是 webpack
这种开发方式帮我们分离了组件, 使开发过程的代码/组件结构更清晰, 而且直接引用 vue.js
是前端 runtime render
, 一个是 compiler render
之后直接执行, 后者效率更高.
之后是效果页面:
(若图片显示较小请在右键在新标签页单独查看)
看图就明白什么意思啦.
还有不明白的请看文档.
[转] Vue + Webpack 组件式开发(练习环境)的更多相关文章
- 组件式开发(Vue)
什么是组件式开发: 组件式开发就是将单个组件组合起来,形成一个大的组件进行页面的开发完成 什么是复合型组件: 复合型组件就是将相同的功能写成一个公用的组件(单元组件),供其他组件使用,就类似于后台开发 ...
- Agile.Net 组件式开发平台 - 组件开发示例
所谓组件式开发平台,它所有的功能模块都是以组件的形式扩展的,下面我来演示一个简单的组件开发例程. Agile.Net开发管理平台项目,已经托管在开源中国码云平台(http://git.oschina. ...
- Agile.Net 组件式开发平台 - 平台系统介绍
平台介绍 Agile.Net 组件式开发平台是一款针对企业级产品的开发框架,平台架构基于SOA服务体系,多层组件式架构打造.平台提供企业应用开发所需的诸如ORM.IOC.WCF.EBS.SOA等分布式 ...
- PIE SDK组件式开发综合运用示例
1. 功能概述 关于PIE SDK的功能开发,在我们的博客上已经分门别类的进行了展示,点击PIESat博客就可以访问,为了初学者入门,本章节将对从PIE SDK组件式二次开发如何搭建界面.如何综合开发 ...
- Agile.Net 组件式开发平台 - 驱动开发示例
首先讲一下概念,此驱动非彼驱动.在Agle.Net中我们将组件规划成两种类型,一种是基于业务的窗体组件,一种是提供扩展功能的驱动组件. 打个比方例如一般系统中需要提供身份证读卡功能,然而市面上有很多种 ...
- Agile.Net 组件式开发平台 - 服务开发示例
在上一篇文章中已经讲解了组件的开发,这篇文章讲解平台服务开发. Agile.Net开发管理平台项目,已经托管在开源中国码云平台(http://git.oschina.net) 登陆码云平台进入项目主页 ...
- 基于TypeScript的FineUIMvc组件式开发(开头篇)
了解FineUIMvc的都知道,FineUIMvc中采用了大量的IFrame框架,对于IFrame的优缺点网上也有很多的讨论,这里我要说它的一个优点“有助于隔离代码逻辑”,这也是FineUIMvc官网 ...
- vue.js组件化开发实践
前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了下面的内容.借油开车. 组件化 需求一到,接就是怎么实现,技术选型自然 ...
- 【06】Vue 之 组件化开发
组件其实就是一个拥有样式.动画.js逻辑.HTML结构的综合块.前端组件化确实让大的前端团队更高效的开发前端项目.而作为前端比较流行的框架之一,Vue的组件和也做的非常彻底,而且有自己的特色.尤其是她 ...
随机推荐
- idea打开项目,没有项目文件,文件报红
删除项目文件夹中的.idea文件,重启idea,再执行如下操作.
- 【BZOJ5492】[HNOI2019]校园旅行(bfs)
[HNOI2019]校园旅行(bfs) 题面 洛谷 题解 首先考虑暴力做法怎么做. 把所有可行的二元组全部丢进队列里,每次两个点分别向两侧拓展一个同色点,然后更新可行的情况. 这样子的复杂度是\(O( ...
- [AMD驱动]解决AMD驱动的1603错误
官方:https://www.amd.com/en/support/kb/faq/gpu-kb1603 其实把更改的文档 下载 音乐等默认目录恢复到C盘(或任意一个可访问的路径),就可以正常安装了.
- LoadRunner【第一篇】下载、安装、破解
loadrunner11下载 loadrunner11大小有4g多,相对另外一款开源的性能测试工具jmeter来说,是非常笨重的了,网上很多,大家可以搜索,也可以点击右侧加群获取安装包. loadru ...
- Oracle Database 快捷版 安装 连接
Oracle Database 快捷版 11g 第 2 版 下载地址:http://www.oracle.com/technetwork/cn/database/database-technologi ...
- 读zepto源码之工具函数
读zepto源码之工具函数 Zepto 提供了丰富的工具函数,下面来一一解读. 源码版本 本文阅读的源码为 zepto1.2.0 $.extend $.extend 方法可以用来扩展目标对象的属性.目 ...
- echarts 修改y轴name的样式
option = { xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sa ...
- HDU 5984(求木棒切割期望 数学)
题意是给定一长为 L 的木棒,每次任意切去一部分直到剩余部分的长度不超过 D,求切割次数的期望. 若木棒初始长度不超过 D,则期望是 0.000000: 设切割长度为 X 的木棒切割次数的期望是 F( ...
- LFYZ-OJ ID: 1024 火车站
火车过站 问题描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人.从 ...
- Ubuntu操作用户账户
Git Gerrit $是普通管员,#是系统管理员,在Ubuntu下,root用户默认是没有密码的,因此也就无法使用(据说是为了安全).想用root的话,得给root用户设置一个密码: sudo pa ...