关于 Vue & Webpack 的说明
这是一篇关于 Vue & Webpack 的笔记。
引言
这是一篇关于 Vue & Webpack 的笔记。
背景
Angular、React 和 Vue。 CommonJS、Typescript、ES5、ES6 (ES2015) 和 Babel。 SystemJS 和 Webpack。 有太多的术语需要学习,有太多的术语做着相同的事情,而且还相当固执己见。 在 Angular、React 和 Vue 中,Vue 鲜为人知,但拥有最好的文档,并且至少努力做到不那么固执己见,而且正在迅速 gaining its popularity(获得普及)。
- Angular - Angular 是重量级的。“zone.js” 变更检测方法使默认行为全局化。它也使得性能优化非常复杂和繁琐;
- React - React 更轻量级,而且不那么固执己见。“setState()” 函数减轻了变更检测的繁重工作。但如果状态更改发生在多个组件中,则需要额外的工作;
- Vue - Vue 更轻量级,而且不那么固执己见。“Object.defineProperties()” 变更检测方法精确地指出了已更改的内容。它结合了 Angular 和 React 的优点。它是全局的,而且效率很高。
这篇笔记是一个例子,它使用 ES5 Javascript 和 webpack 实现了两个小型 Vue 应用程序的版本。因为 Vue 和 Vue CLI 有清晰的文档,这个例子可能不会为您提供太多价值。它仅仅用于对 Vue 进行小型评估。如果您想快速入门并想获得一个正在运行的示例,可以下载此示例。
Node 应用程序
附带的是一个简单的 Node 应用程序。该应用程序的唯一目的是服务于“vue-example”目录中的静态内容,该目录包含两个 Vue SPA 应用程序。Node 应用程序的入口是“app.js”文件。
var express = require('express'),
http = require('http'),
path = require('path');
var app = express();
app.set('port', 3000);
app.use(function (req, res, next) {
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
next();
});
app.use(express.static(path.join(__dirname, 'vue-example')));
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
要运行该应用程序,您需要在应用程序的根目录中发出以下命令来安装“node_modules”。
npm install
然后,您可以通过以下命令启动 Node 应用程序。
node app.js
ES5 Javascript Vue SPA
在“plain-version”目录中,我按照 Vue 文档的说明创建了一个简单的 Vue SPA。它使用 ES5 Javascript 实现,可以直接加载到浏览器中。为了简单起见,所有 CSS、Javascript、HTML 和 Vue 模板都包含在“index.html”文件中。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>vue-example-plain</title> <style type="text/css"> * { box-sizing: border-box; } .container { width: 400px; height: 400px; border: 1px solid red; border-radius: 6px; display: flex; flex-wrap: wrap; justify-content: space-evenly; align-content: flex-start; } .item { width: 80px; height: 80px; border-radius: 50%; background-color: blue; margin-top: 12px; cursor: pointer; } .item.red { background-color: red; } </style> <script src="https://cdn.jsdelivr.net.cn/npm/vue"></script> <script type="text/x-template" id="container-template"> <div class="container"> <item v-for="(item, index) in items" v-on:itemIsClicked="itemIsClicked" v-bind:index="index" v-bind:value="items[index]"></item> <div style="width: 200px; height: 0px;"></div> <div> </script> <script type="text/x-template" id="item-template"> <div class="item" v-on:click="itemClicked" v-bind:class="{red: value == 1}"></div> </script> <script type="text/javascript"> let item = { template: '#item-template', props: ['index', 'value'], methods: { itemClicked: function() { this.$emit('itemIsClicked', this.index); } } }; let container = { template: '#container-template', components: { 'item': item }, data: function() { return { items: new Array(16).fill(0) }; }, methods: { itemIsClicked: function(i) { let v = this.items[i]; this.$set(this.items, i, (v == 0)? 1:0); } } }; window.onload = function() { let app = new Vue({ el: '#app', components: { 'container': container } }); }; </script> </head> <body> <div id="app"><container></container></div> </body> </html>
根据 Vue 文档中的说明,Vue 库是从 CDN “https://cdn.jsdelivr.net.cn/npm/vue” 链接的。这个简单的 Vue SPA 有两个 Vue 组件。
- “item”组件是一个子组件,用于显示一个圆圈;
- “container”组件是父组件。它使用 “v-for” 绑定在其内部添加 16 个项目。它还接收来自子组件的事件来切换圆圈的颜色;
- SPA 在 “window.onload” 事件中被初始化到 “<div id="app">” 中。
这个 SPA 很简单,但它实际上回答了创建 Vue 应用程序时最常被问到的问题,如下所示。
- 如何初始化 Vue 应用程序;
- 如何使用子组件;
- 如何将数据作为 props 传递给子组件;
- 如何将 CSS 类绑定到组件的数据或 props;
- 如何挂钩到 Vue 组件的用户事件;
- 如何从子组件 “$emit” 事件到父组件;
- 如何更新数据中的某个条目,如果它是 Array 类型,以便 Vue 在条目更改时能够感知到。
当 Node 应用程序运行时,您可以通过 URL - “https://:3000/plain-version/” 访问 Vue SPA。
如果您单击圆圈,您应该会看到颜色按预期切换。
Webpack Vue SPA
在 Vue 文档的帮助下,使用纯 ES5 Javascript 通过 Vue 创建 SPA 是一个简单而愉快的体验。它轻量级且运行速度快。因为 Vue 是轻量级的,所以 Vue 应用程序也很容易维护。但是,如果您是固执己见的人,您可能不喜欢这样一个事实:您可以编写仅在 Web 浏览器中运行而无需转换的 ES5 Javascript 应用程序。您也可能觉得 ES5 Vue 应用程序的模块化程度较低。为了使其模块化,Vue 实际上支持 webpack。
在“wpack-version”目录中,我创建了一个几乎完全相同的 Vue SPA,它使用了 webpack。正如 Vue 文档所建议的,使用 webpack 创建 Vue 应用程序的最佳方法是 Vue CLI。实际上,这个 SPA 是由 Vue CLI 创建的。我只是对其进行了一些小的修改。
NPM 依赖
要将 webpack 用于 Vue 应用程序,我们需要一组 NPM 依赖。现在让我们看看“wpack-version”目录中的“package.json”文件。
{ "name": "a-vue-example-wpack", "description": "a-vue-example-wpack-version", "version": "1.0.0", "author": "Song Li", "license": "MIT", "private": true, "scripts": { "build-dev": "cross-env NODE_ENV=dev webpack --color --watch", "build-prod": "cross-env NODE_ENV=production webpack --hide-modules" }, "dependencies": { "vue": "^2.5.11" }, "devDependencies": { "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "babel-preset-stage-3": "^6.24.1", "cross-env": "^5.0.5", "css-loader": "^0.28.7", "file-loader": "^1.1.4", "vue-loader": "^13.0.5", "vue-template-compiler": "^2.4.4", "webpack": "^3.6.0", "webpack-dev-server": "^2.9.1", "url-loader": "0.6.2" } }
Vue 组件
当使用 webpack 编写 Vue 应用程序时,我们需要将每个组件创建为一个 “vue” 文件。以下是 “item.vue” 文件。
<template> <div class="item" v-on:click="itemClicked" v-bind:class="{red: value == 1}"></div> </template> <script> export default { name: 'item', props: ['index', 'value'], methods: { itemClicked: function() { this.$emit('itemIsClicked', this.index); } } }; </script> <style scoped> .item { width: 80px; height: 80px; border-radius: 50%; background-color: blue; margin-top: 12px; cursor: pointer; } .item.red { background-color: red; } </style>
然后,“item”组件被导入并在 “container.vue” 文件中的“container”组件中使用。
<template> <div class="container"> <img src="./assets/logo.png"> <item v-for="(item, index) in items" v-on:itemIsClicked="itemIsClicked" v-bind:key="index" v-bind:index="index" v-bind:value="items[index]"></item> <div style="width: 200px; height: 0px;"></div> </div> </template> <script> import item from './item.vue'; export default { name: 'container', components: { 'item': item }, data: function() { return { items: new Array(16).fill(0) }; }, methods: { itemIsClicked: function(i) { let v = this.items[i]; this.$set(this.items, i, (v == 0)? 1:0); } } }; </script> <style scoped> .container { width: 400px; height: 600px; border: 1px solid red; border-radius: 6px; display: flex; flex-wrap: wrap; justify-content: space-evenly; align-content: flex-start; } .container>img { width: 350px; } </style>
“container”组件被导入并在 “main.js” 文件中启动。
import Vue from 'vue'; import container from './container.vue'; new Vue({ el: '#app', render: h => h(container) });
“webpack.config.js”
“webpack.config.js” 文件配置 webpack 如何打包应用程序。
var path = require('path') var webpack = require('webpack') module.exports = { entry: './app/main.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/wpack-version/dist/', filename: 'build.js' }, module: { rules: [ { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: {} } }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/, use: [{ loader: 'url-loader', options: { limit: 10240 } }] } ] }, resolve: { alias: { 'vue$': 'vue/dist/vue.esm.js' }, extensions: ['*', '.js', '.vue', '.json'] } }; if (process.env.NODE_ENV === 'production') { module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.optimize.UglifyJsPlugin({})])}
“.babelrc” 文件
这个小的 “.babelrc” 文件是一个隐藏文件。但它需要位于“wpack-version”目录中。没有它,您将无法成功进行生产 webpack 构建。
{ "presets": [ ["env", { "modules": false }], "stage-3" ] }
“index.html”
由 webpack 在 “/wpack-version/dist/” 目录中构建的 “build.js” 文件将被加载到 “index.html” 中供浏览器渲染应用程序。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>vue-example-wpack</title> <style type="text/css"> * { box-sizing: border-box; } </style> </head> <body> <div id="app"></div> <script src="/wpack-version/dist/build.js"></script> </body> </html
构建并运行
为了构建“wpack-version”目录中的 SPA,您需要从 Node 应用程序的根目录发出以下命令来安装“wpack-version”目录中的 “node_modules”。
npm -prefix vue-example/wpack-version install
要进行开发 webpack 构建,您可以发出以下命令。它将构建 SPA 并设置一个监视器。每当您对相关文件进行任何更改时,监视器将触发另一个构建,以节省您手动触发新构建以反映所做更改的精力。
npm -prefix vue-example/wpack-version run build-dev
如果您想最小化您的 webpack 包,可以使用以下命令触发生产构建。
npm -prefix vue-example/wpack-version run build-prod
生产构建仅应用于生产发布。最小化过程是一个缓慢的过程。在开发过程中,当您需要不断地进行更改和重新构建 SPA 时,所需的时间似乎太长了。
当 Node 应用程序运行时,您可以通过 URL - “https://:3000/wpack-version/” 访问 SPA 的 webpack 版本。如果您在浏览器中检查 Vue 徽标,您会发现 webpack 不仅打包了所有 Vue 组件,还实际上将一个图像文件转换为 Base64 格式并将其添加到包中。
关注点
- 这是一篇关于 Vue & Webpack 的笔记;
- 希望您喜欢我的博文,并希望这篇笔记能以某种方式帮助您。
历史
首次修订 - 2017 年 12 月 26 日