[转] 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, 那相应的安装包少不了, 这里我们使用 [email protected] 和 [email protected]:

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 的必装 loadercss-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 函数的话就直接执行 rendertemplate 字段下的内容会被忽略. 而执行编译后的 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 更清晰, 将其加到了 [email protected] 的配置文件中的 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 之后直接执行, 后者效率更高.

之后是效果页面:

 (若图片显示较小请在右键在新标签页单独查看)

看图就明白什么意思啦.

还有不明白的请看文档.

原文地址:https://www.cnblogs.com/chris-oil/p/9934229.html

时间: 2024-10-05 05:32:31

[转] Vue + Webpack 组件式开发(练习环境)的相关文章

注入式类的写法,解耦,组件式开发,沙箱

沙箱(网络编程虚拟执行环境) Sandboxie(又叫沙箱,沙盘)即是一个虚拟系统程序,允许你在沙盘环境中运行浏览器或者其他应用. 因此运行会产生的变化可以随后删掉. 它创造了一个类似沙盒的独立作业环境,在其中内部运行并不会对硬盘产生永久的影响. 其为一个独立的 虚拟环境,可用以测试不受信任的应用程序或上网行为. 沙箱是一种按照安全策略限制程序行为的执行环境. 早期主要用于测试可疑软件等,比如黑客们为了试用某种病毒或者不安全产品,往往可以将它们在沙箱环境中运行. 经典的沙箱系统的实现途经一般是通

PIE SDK组件式开发综合运用示例

1. 功能概述 关于PIE SDK的功能开发,在我们的博客上已经分门别类的进行了展示,点击PIESat博客就可以访问,为了初学者入门,本章节将对从PIE SDK组件式二次开发如何搭建界面.如何综合开发进行详细的讲解. 2. 功能实现 2.1.界面搭建 最终的界面如下图所示: 图1最终结果图 2.1.1 新建项目 选择“Window窗体应用程序”,设置程序的名称和保存路径即可.(新建完成后可以将程序的窗体名称右键重命名为“FormMain”,,将窗体界面的属性的Text设置名称为“PIE应用程序”

前端全栈架构,组件式开发,响应式开发,全栈工程师架构,用户界面架构,企业级架构项目实战

我本是一名文科专业半路出家的前端开发人员,从最初只会切图和写CSS.Html到现在会写点JS,一路坑坑洼洼,也是经历了很多,从2010年开始就用WordPress开设了自己的博客,虽然内容零零散散的并不多,但是多多少少也留下了时光的缩影,一直希望自己有一个自留地.用Node.js做服务端替换WordPress是去年的一个想法,由于一直腾不出时间,所以拖到了现在.当然了WordPress作为全球用户量最广的开源博客程序,易用性等诸多好处无可厚非,光自己的博客在过去几年就用了很多套模板,也用它做过很

基于TypeScript的FineUIMvc组件式开发(简介)

不熟悉FineUI的可以访问其官方网站(http://www.fineui.com),在这里我从我的个人角度说一下FineUI,FineUI有多个版本,但主要基于2种架构,一种是基于Asp.net WebForm,别一种是基于Asp.net Mvc. 在WebForm版本下,虽然FineUI是一个前端构架,但在一些常规简单项目中几乎不用写JS代码,除了首次请求页面,后续的操作都是基于Ajax的,而JS代码都是由服务器端动态生成,并放到客户端执行,这也是FineUI的一大特点.了解WebForm的

基于TypeScript的FineUIMvc组件式开发(开头篇)

了解FineUIMvc的都知道,FineUIMvc中采用了大量的IFrame框架,对于IFrame的优缺点网上也有很多的讨论,这里我要说它的一个优点"有助于隔离代码逻辑",这也是FineUIMvc官网对它的描述.IFrame在网页上下文中是完全独立的,这样也就不存在了样式及脚本之间的冲突问题.但由于IFrame与上下文之间是隔离的,在交互上也给我们带来了一些不便. 在接下来的文章中,我将主要介绍如何使用TypeScript对FineUIMvc进行组件式开发,而这里的组件就是基于IFra

vue.js组件化开发实践

前言 公司以往制作一个H5活动,特别是有一定统一结构的活动都要每次用html.css.js滚一次重复的轮子,费时费力.后来接到了一个基于模板的活动发布系统的需求,于是就有了下面的内容. 开始 需求一到,接就是怎么实现,技术选型自然成为了第一个问题.鉴于目前web前端mvvm框架的流行,以及组件化开发方式的出现,决定采用vue进行开发. 这里首先简单说下web前端组件化开发方式的历程: 最早的组件化结构,或者叫做组件化1.0时代,代码结构可能如下: 1 - lib/components/calen

Vuejs - 组件式开发

初识组件 组件(Component)绝对是 Vue 最强大的功能之一.它可以扩展HTML元素,封装可复用代码.从较高层面讲,可以理解组件为自定义的HTML元素,Vue 的编译器为它添加了特殊强大的功能.所有的 Vue 组件同时也都是 Vue 的实例,因此可以接受相同的选项对象(除了一些特有的选项)并提供相同的生命周期函数. 再来回顾下 你也许不知道的Vuejs - 花式渲染目标元素 中的代码: 123 <div id="app1"> <helloworld/>&

组件式开发 webapp全站之第一章

1-1课程介绍 略1-2课程安排 课程安排分为两个方面:开发流程和技术实现 1-2-1开发流程 为什么要说流程 每个流程要做什么 各个环节易出现什么问题 问题定责 1-2-2技术实现 技术规划,选型 设计易扩展的开发方案 开发各种图表组件1-3WEB项目开发流程介绍 1-3-1为什么要说开发流程 1.可以提升开发效率 2.防止背锅 1-3-2开发流程的环节划分 开发流程划分为三个环节:开发前,开发中,开发后 1)开发前 产品功能设计 产品经理 产出:产品需求文档 视觉/交互设计 美工 产出:视觉

组件式开发

为什么要做组件化? 无论前端也好,后端也好,都是整个软件体系的一部分.软件产品也是产品,它的研发过程也必然是有其目的.绝大多数软件产品是追逐利润的,在产品目标确定的情况下,成本有两个途径来优化:减少部署成本,提高开发效率. 减少部署成本的方面,业界研究得非常多,比如近几年很流行的“去IOE”,就是很典型的,从一些费用较高的高性能产品迁移到开源的易替换的产品集群,又比如使用Linux + Mono来部署.net应用,避开Windows Server的费用. 提高开发效率这方面,业界研究得更多,主要