说明

这是我根据慕课网上的一个课程 Vue+Webpack打造todo应用 过程一步步搭下来的框架,去掉了业务相关的逻辑。

项目最终的效果包括了引入vue框架;使用CSS预处理器;使用babel;引用图片等静态资源;区分开发环境与生成环境,并做相应优化等。基本接近真正做项目时候的配置。

但是!! 毕竟是我个人根据练习课程搭的框架,跟真实工作可能有区别,请谨慎直接用于工作环境!!!

项目的最终成果看这里:https://gitee.com/Dandelion_/vue-webpack-scaffold

Tips:项目里面的 commit 对应文章的每一小节,所以大家善用 git checkout <commit> 命令可以很方便地切换到某个 commit 看当前版本的文件变化哦。当然直接看项目的 commit 列表也行啦。


0. 前言

首先不得不说 vue-cli + vue-webpack 模版真的很方便,vue init webpack my-vue-project 就搭好框架了,而且开发环境生产环境都有了。npm run dev 启动开发环境,npm run build 发布生产环境。几个命令全部搞定了。但是模版有时候可能不够灵活,或者我们想修改其中一些东西,面对这些需求的时候,理解怎么搭建起这个 vue + webpack 的环境还是很有用的。那最快捷的方式,当然是自己从头开始搭一遍啦。心动不如行动,走~~


1. 新建项目

因为不用 vue-cli 和 vue 模版,所以一开始我们就建个空文件夹。

mkdir my-vue-project
cd my-vue-project
npm init # 初始化项目。这时候会问你一些问题,比如项目名称、作者之类的,照着提示回答问题就好

2. 安装基本的 npm 包

首先肯定要安装 vuewebpack。然后 webpack 4.x已经把 cli 单独拎出来了,所以还要安装 webpack-cli;然后因为 webpack 本身其实直接能处理的只有 js 资源,是通过各种 loader 让其他资源可以被 webpack 打包处理的。那么现在我们要用 vue 写单文件组件(就是 .vue 文件),所以就还要安装 vue-loader

npm install vue vue-loader webpack webpack-cli --save-dev # --save-dev表示这些只是开发环境所需的依赖

3. 添加项目各种入口文件

入口文件都是很普遍的那种,比如根目录下的 index.htmlsrc 文件夹下的 main.jsapp.vue 等等,我就不一一解释了。

添加入口文件后的项目目录如下:

.
├── dist/
| ├── ...
├── src/
| ├── main.js
| ├── app.vue
├── node_modules/
| ├── ...
├── index.html
├── package.json

更详细的项目结构和具体文件内容可以看 这个commit

4. 添加 webpack 配置文件

在项目根目录下添加 webpack.config.js 文件。内容如下:

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin'); module.exports = {
entry: path.join(__dirname, 'src/main.js'), // 项目总入口js文件
// 输出文件
output: {
path: path.join(__dirname, 'dist'), // 所有的文件都输出到dist/目录下
filename: 'bundle.js'
},
module: {
rules: [{
// 使用vue-loader解析.vue文件
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.css$/,
// 要加上style-loader才能正确解析.vue文件里的<style>标签内容
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new VueLoaderPlugin() // 最新版的vue-loader需要配置插件
]
};

5. 添加构建脚本

package.json 文件的 scripts 属性里添加 build 脚本

   "scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack --config webpack.config.js"
},

因为我们添加了一些引用,比如 style-loadercss-loader 等,所以也要安装相应的包。

npm i style-loader css-loader vue-template-compiler --save-dev

安装好依赖后运行 npm run build 来构建项目。

构建成功后在项目根目录启动一个静态资源服务器,然后浏览就可以看到以下页面了。

6. 添加图片、CSS 预处理器等 loader

图片 loader 用的是 url-loader,它依赖于 file-loader,比 file-loader 多了一个可以比小于一定大小的图片直接转化成 base64 的形式插入到 html 页面,可以减少网络请求。

CSS 预处理器 我选的是 SASS

安装依赖:

npm i file-loader url-loader node-sass sass-loader --save-dev

修改 webpack.config.js

		module.exports =
{
test: /\.css$/,
// 要加上style-loader才能正确解析.vue文件里的<style>标签内容
use: ['style-loader', 'css-loader']
+ },
+ {
+ test: /\.scss$/,
+ use: [
+ // 处理顺序是从sass-loader到style-loader
+ 'style-loader',
+ 'css-loader',
+ 'sass-loader'
+ ]
+ },
+ {
+ test: /\.(gif|jpg|jpeg|png|svg)$/i,
+ use: [{
+ loader: 'url-loader',
+ options: {
+ // 当文件大小小于limit byte时会把图片转换为base64编码的dataurl,否则返回普通的图片
+ limit: 8192,
+ name: 'dist/assest/images/[name]-[hash:5].[ext]' // 图片文件名称加上内容哈希
+ }
+ }]
}
]
},
...

测试一下:

添加 src/assets/styles/global.scss 文件

+.play {
+ background-image: url('../images/play.png');
+ background-repeat: no-repeat;
+ width: 64px;
+ height: 64px;
+ padding: 0;
+ border: 0;
+ background-color: transparent;
+ margin: 0;
+ cursor: pointer;
+}

src/main.js 引用 global.scss

 import Vue from 'vue'; // 从node_modules引入vue类库
import App from './app.vue'; // ES6 语法,相当于 import { default as App } from './app.vue'。因为app.vue用过的是export default {...},所以可以这样写 +import './assets/styles/global.scss';
+
new Vue({
el: '#app',
components: {

运行 npm run build,刷新页面,能看到如下效果:

button 的背景图是 1.97kb,小于 8192byte,可以看到图片已经被转换成 base64 的内容了。

7. 添加 postcss-loader + autoprefixer,自动添加 css 浏览器前缀

安装依赖:

npm i postcss-loader autoprefixer --save-dev

新增 postcss 配置文件 postcss.config.js

const autoprefixer = require('autoprefixer');

module.exports = {
plugins: [
autoprefixer({
browsers: ['last 5 versions']
})
]
};

修改 webpack.config.js

	...
module: {
rules: [
...
{
test: /\.css$/,
use: [
// 要加上style-loader才能正确解析.vue文件里的<style>标签内容
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1
}
},
'postcss-loader'
]
},
{
test: /\.scss$/,
use: [
// 处理顺序是从sass-loader到style-loader
'style-loader',
'css-loader',
{
loader: 'postcss-loader',
options: {
sourceMap: true
}
},
'sass-loader'
]
},
...

测试一下:

修改 index.html

     <h1>一个用 vue + webpack 搭建的脚手架框架</h1>
<div id="app"></div>
<button class="play"></button>
+ <div class="flex">
+ <div class="flex-item"></div>
+ <div class="flex-item"></div>
+ <div class="flex-item"></div>
+ </div>
<script src="/dist/bundle.js"></script>
</body>

修改 global.scss


+.flex {
+ display: flex;
+ border: solid #000 2px;
+ width: 300px;
+ height: 100px;
+ .flex-item {
+ flex: 1;
+ background-color: #1296db;
+ border: solid #fff 1px;
+ }
}

运行 npm run build,刷新页面,能看到如下效果:



可以看到 flex 已经加上了浏览器前缀了。

8. 添加 babel-loader,转译 es6 代码为 es5 代码

添加.babelrc文件

{
"presets": [
"env"
],
"plugins": [
"transform-vue-jsx"
]
}

安装依赖

npm i babel-loader@7 babel-core babel-preset-env --save-dev

修改 webpack.config.jsmodule.rules 再加一条:

{
test: /\.js$/,
exclude: /(node_modules|bower_components)/, // 不处理这两个文件夹里的内容
loader: 'babel-loader'
}

测试一下:

修改 main.js,加上以下代码

// 测试babel-loader
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
} sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
}

在浏览器查看输出,如下图:

如果注释掉 webpack.config.jsbabel-loader 这条规则,则编译之后如下:

可以看到 babel-loader 已经起作用了。

9. 添加 html-webpack-plugin,自动生成 index.html 的内容

添加 HtmlWebpackPlugin,在 dist 文件夹也生成 index.html 页面,而且会自动加上对项目入口 js 文件的引用,也就是说我们自己写的 index.html 可以不用再手动指定 js 文件了,它会把 webpack 配置里的 entry 当中指定的 js 都插入到生成的 index.html 中,而且当输出的文件添加上 hash 值时也可以自动跟踪。

安装依赖

npm i html-webpack-plugin --save-dev

修改 webpack.config.js

 const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
+const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = {
entry: path.join(__dirname, 'src/main.js'), // 项目总入口js文件
// 输出文件
output: {
path: path.join(__dirname, 'dist'),
- filename: 'bundle.js'
+ filename: 'bundle-[hash].js' // 输出文件的名称加上hash值
},
module: {
rules: [{
...
]
},
plugins: [
- new VueLoaderPlugin() // 最新版的vue-loader需要配置插件
+ new VueLoaderPlugin(), // 最新版的vue-loader需要配置插件
+ new HtmlWebpackPlugin({
+ filename: 'index.html', // 生成的文件名称
+ template: 'index.html', // 指定用index.html做模版
+ inject: 'body' // 指定插入的<script>标签在body底部
+ })
]
};

修改 index.html,把原来引用 bundle.js<script> 去掉。

然后我们 build 一下,看 dist 文件夹的输出。

可以看到 dist 文件夹下多了 index.html 文件,而且文件内容自动加上了编译出来的 bundle.js 文件的引用。

10. 添加 clean-webpack-plugin,每次 build 之前可以自动先清除输出文件夹

如果我们对输出的文件名称加上了哈希值的话,每次修改之后的哈希值都不一样,就是每次都生成了一个新的文件,那旧的那些其实就是多余的文件了(上面那张图的 dist 文件夹可以看出来)。因此我们可以用 clean-webpack-plugin 这个插件,在每次 build 之前先清除输出文件夹。

安装依赖

npm i clean-webpack-plugin --save-dev

修改 webpack.config.jsplugins 数组添加一项

 const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CleanWebpackPlugin = require('clean-webpack-plugin'); module.exports = {
...
plugins: [
new VueLoaderPlugin(), // 最新版的vue-loader需要配置插件
new HtmlWebpackPlugin({
filename: 'index.html', // 生成的文件名称
template: 'index.html', // 指定用index.html做模版
inject: 'body' // 指定插入的<script>标签在body底部
}),
+ new CleanWebpackPlugin(['dist'])
]
};

11. 添加 webpack-dev-server,配置更友好的开发环境

webpack-dev-server 可以在本地启动一个服务器,而且当有任何文件修改的时候会自动重新打包,并且刷新浏览器页面。此外 devServer 还有很多其他配置项,让我们可以更方便的开发。

安装依赖

npm i webpack-dev-server cross-env --save-dev

用上 cross-env 是因为我们接下来要修改 package.json 里的 scripts,而不同的平台写scripts 的方式不一样。

修改 package.json 里的 scripts

    ...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
- "build": "webpack --config webpack.config.js"
+ "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
+ "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js"
},
....

修改 webpack.config.js,这次改得比较多,可以看这里的 commit detail

配置好以后我们可以运行 npm run dev 命令启动一个服务器了

12. 配置生产环境 css 单独分离打包,方便浏览器缓存

安装依赖

npm i mini-css-extract-plugin --save-dev

修改 webpack.config.js,改动的地方看这个 commit detail

13. 单独打包类库文件

因为类库文件是不用像业务代码一样经常更新的,单独打包可以让它们在浏览器里缓存,提高加载速度。

修改 webpack.config.js,改动的地方看这个 commit detail


到这里基本的配置都完成了,一个基础的 vue 项目框架就搭好啦,接下来我们只需要专注于添加自己项目的业务逻辑页面和代码就好了。愉快地敲(xie)代(bug)码去吧~~

PS: 这个是目前为止用到的配置,其实真实生成环境要做的优化应该还有不少,比如图片压缩处理等等,大家要根据自己的项目需要来扩展哦。如果以后有用到其他的插件比较通用的应该会更新这篇文章。嗯,也就是不定期无规律看心情更新2333【逃。。】


本文首发于我的个人网站【https://dandelion-drq.github.io】,欢迎访问。

不使用 vue-cli 与 vue 模版,使用 Vue2.x + webpack4.x 从零开始一步步搭建项目框架的更多相关文章

  1. [Vue CLI 3] vue inspect 的源码设计实现

    首先,请记住: 它在新版本的脚手架项目里面非常重要 它有什么用呢? inspect internal webpack config 能快速地在控制台看到对应生成的 webpack 配置对象. 首先它是 ...

  2. Vue CLI及其vue.config.js(一)

    有时候我们为了快速搭建一个vue的完整系统,经常会用到vue-cli,vue-cli用起来很方便而且命令简单容易上手,但缺点是在构建的时候我感觉有一些慢,因为CLI 服务 (@vue/cli-serv ...

  3. 使用Vue CLI构建Vue项目

    第一步:首先在控制台输入vue --version,如果出现版本号则进入第三步:否则进入第二步: 第二步:输入npm install cnpm -g --registry=https://regist ...

  4. [Vue 牛刀小试]:第十六章 - 针对传统后端开发人员的前端项目框架搭建

    一.前言 在之前学习 Vue 基础知识点的文章中,我们还是采用传统的方式,通过在 html 页面上引用 vue.js 这个文件,从而将 Vue 引入到我们的项目开发中.伴随着 Node.js 的出现, ...

  5. [Vue CLI 3] @vue/cli-plugin-eslint 源码分析

    熟悉 eslint-loader 的同学一般如下配置: 设置一下几项: test : A condition that must be met(一般是处理对应文件的正则) exclude : A co ...

  6. Vue CLI 3.x 简单体验

    文档 中文文档 补充于02月10日 vue脚手架的3.x版本已经在开发中,现在还处于alpha版本.我们来看看有哪些变化. 使用 npm install -g @vue/cli 命名方式已经改为npm ...

  7. [转]Vue CLI 3搭建vue+vuex 最全分析

    原文地址:https://my.oschina.net/wangnian/blog/2051369 一.介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统.有三个组件: CLI:@ ...

  8. vue cli脚手架使用

    1.安装nodejs,npm https://www.cnblogs.com/xidianzxm/p/12036880.html 2.安装vue cli sudo npm install -g @vu ...

  9. ubuntu下安装vue/cli提示No command 'vue' found

    通过官方指令 npm install -g @vue/cli 安装vue脚手架提示: No command 'vue' found, did you mean: Command 'vpe' from ...

随机推荐

  1. 【IT笔试面试题整理】删除无序链表中重复的节点

    [试题描述]定义一个函数,输入一个链表,删除无序链表中重复的节点 [参考代码] 方法一: Without a buffer, we can iterate with two pointers: &qu ...

  2. 让浏览器兼容ES6语法(gulp+babel)

    使用gulp+babel搭建ES6环境 前言 我们查阅资料可以知道ECMAScript 2015(简称ES6)已经于2015年发布,由于用户使用的浏览器版本在安装的时候可能早于ES6的发布,而到了今天 ...

  3. Spring @Valid

    @Valid基本用法 强烈推荐如果要学习@Valid JSR303, 建议看这里的API  Bean Validation规范 ! Controller控制器中在需要校验的实体类上添加  @Valid ...

  4. Spring中使用变量${}的方式进行参数配置

    在使用Spring时,有些情况下,在配置文件中,需要使用变量的方式来配置bean相关属性信息,比如下面的数据库的连接使用了${}的方式进行配置,如下所示: <bean id="data ...

  5. .1-浅析express源码之入口文件

    鸽了鸽了,webpack源码大垃圾,看了那么久,感觉自己越来越渣……还是换个口味,node了解一下? 尝试从express框架源码入手,学习一下node的http模块相关的知识. 入口文件 先从框架的 ...

  6. MVC实现更新数据库的数据

    经过一系列MVC的练习,如数据库的数据显示,添加,删除等,还差一个功能,就是更新,那本次练习的是MVC对数据库的数据进行更新. 写好更新的存过程: 有了存储过程,可以写实体(Entity)的方法了.写 ...

  7. win2d 图片水印

    本文告诉大家如何使用 win2d 给图片加上水印. 安装 首先需要使用 Nuget 安装 win2d ,安装参见win10 uwp win2d 如果没有更新 dot net core 那么在运行可能会 ...

  8. 深入理解.NET MemoryCache

    摘要 MemoryCache是.Net Framework 4.0开始提供的内存缓存类,使用该类型可以方便的在程序内部缓存数据并对于数据的有效性进行方便的管理,借助该类型可以实现ASP.NET中常用的 ...

  9. Java多线程--JDK并发包(1)

    Java多线程--JDK并发包(1) 之前介绍了synchronized关键字,它决定了额一个线程是否可以进入临界区:还有Object类的wait()和notify()方法,起到线程等待和唤醒作用.s ...

  10. Software-Defined Networking之搬砖的故事

    在很久很久以前,有一个村子. 村里的每一户,都有一个男人和一个女人. 每一户,都以搬砖为生. 从不同的地方,搬到不同的地方. 男人负责搬砖,女人负责告诉男人往哪搬. 每个家庭,都服从村委会的指挥. 村 ...