Vue 2.x + Webpack 4.x的那些事---萌新必备

大家好,本人名叫苏日俪格,现在很多的项目都使用了webpack,现在最火的也就是vue和webpack结合来完善一个项目,由于介入了一个有几年历史的产品,第一步不得不看看webpack的配置项,看看项目中的哪些部分被模块化了,因为想要更多的理解webpack,查找了一些资料看了很多教程和API,测试了一个没有使用vue脚手架的项目(ps:强烈建议新手务必远离vue-cli,这东西是给有很多年开发经验的老手来提高开发效率的,并不适合学习),下面我会把我对webpack的理解跟大家分享一下,本文纯属个人理解,有哪里不对的地方请在评论区指出,大家一起学习共同进步。

听到webpack这个词,就会有很多人也包括我都会想到gulp,认为二者都是自动化构建工具;其实不是这样的,在这里我先介绍二者的异同:

  • gulp:是一种自动化构建工具,能够提升我们的开发效率,也能提升浏览器运行速度,譬如它能压缩js/css等文件的代码,还能编译less/sass,能完成页面的自动刷新等功能
  • webpack:是一种模块化管理方案/模块打包工具,在他的眼里就是万物皆模块,可以用loader(加载器/转换器)把任何一个文件资源打包成浏览器认识的JavaScript模块,还可以将按需加载的模块进行异步加载

webpack特点

  • Webpack 有两种组织模块依赖的方式,同步和异步。异步依赖作为分割点,形成一个新的块。在优化了依赖树后,每一个异步区块都作为一个文件被打包。
  • Webpack 本身只能处理原生的 JavaScript 模块,但是 loader 转换器可以将各种类型的资源转换成 JavaScript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。
  • Webpack 有一个智能解析器,几乎可以处理任何第三方库,无论它们的模块形式是 CommonJS、 AMD 还是普通的 JS 文件。甚至在加载依赖的时候,允许使用动态表达式 require(“./templates/” + name + “.jade”)。
  • Webpack 还有一个功能丰富的插件系统。大多数内容功能都是基于这个插件系统运行的,还可以开发和使用开源的 Webpack 插件,来满足各式各样的需求。
  • Webpack 使用异步 I/O 和多级缓存提高运行效率,这使得 Webpack 能够以令人难以置信的速度快速增量编译。

在这里不得不说一下:
webpack、gulp和grunt都是在nodeJs的环境下运行的,而在中大型项目或产品中,nodeJs一般用做中间层,做数据处理和转发,然后再由底层语言进行底层开发,比如我们公司的产品就是这种架构,C++作为底层系统的开发;

看了上面的内容,我们虽然知道了它在项目中用到的好处,可是我们没有见过,没有真凭实据,可以参考一下这个项目的demo,一步一步让你的项目越来越快;那么webpack具体怎么用的呢?下面就来逐步介绍一下,为了大家能学到,我这里新建一个项目做示范:

一、安装vue和webpack
  1. 首先webpack是在node环境下运行的,电脑环境中需要有node和npm,并且node版本必须是v8.5以上的,否则不支持webpack 4。在本地创建一个项目文件夹(ps:文件名不能包含大写字母),输入dos命令npm init来初始化工程,一路回车下来会有一个package.json配置文件生成
  2. 先安装上生产环境的vue,其他的开发环境的依赖包等会单独安装,不理解他们的区别的好好看看–save-dev和–save的区别,development很明显就是我们开发所需要的依赖包,而打包好上线的话是不需要这些包的,一来各种包加起来太大,二来它只是我们开发提高效率的工具而已;
    先输入npm i vue安装上vue
  3. 接着输入npm i webpack vue-loader -D安装webpack和vue-loader
    vue-loader就是我们webpack需要读取vue文件并加载成它所认识的js,之后细心的人就会发现package.json里多了一个devDependencies对象,这就是我们要的开发环境的依赖包
  4. 再安装读取一些静态资源比如:img、style、css的loader和vue-template-compiler(用来编译vue模板),url-loader封装了file-loader,将我们要求的格式的图片转换成计算机的base64编码:
    npm i style-loader css-loader url-loader file-loader vue-template-compiler -D
    还用webpack得安装上webpack-cli:
    npm i webpack-cli -D

以上四步安装完是这个效果:

二、配置webpack并打包项目
  1. 在根目录下创建一个src文件夹,在src下创建一个入口文件index.js和一个vue入口app.vue,所有的模块化操作都是在webpack.config.js下完成的,将该文件放在根目录,因为我没用vue-cli,所以所有的文件需要手动引入,再引入我们的一些css和img的静态资源,把项目的整体结构按照脚手架的结构进行搭建,vue-cli模板不能直接嵌套进项目中,必须理解脚手架,手动的去构建vue项目

app.vue文件:

<template>
<div id="app"></div>
</template>

<script type="text/javascript">
export default {

}
</script>

<style>
</style>

index.js文件:

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

import './assets/style/test.css';

var vm = new Vue({
el: '#app',
render: (h) => h(App) // 通过创建DOM元素返回参数h将App挂载,h即为hyperscript,用来实现虚拟DOM的
});

webpack.config.js文件:

const Path = require('path'); // 从node上导入path
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // webpack 4版本之后加的,之前的版本不需要这个

let config = {
entry: Path.resolve(__dirname, './src/index.js'), // 以join拼接path的形式配置绝对路径,相对路径打包后找不到会报错
output: {
filename: 'vendor.build.js',
path: Path.join(__dirname, 'dist')
},
module: {
rules: [{
test: /\.vue$/,
loader: 'vue-loader'
}, {
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}, {
test: /\.(png|jpg|jpeg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 1024, // 判断图片的大小 如果小于1024就会转换成base64
name: '[name].[ext]' // 输出图片的名字 ext是扩展名
}
}
}]
},
plugins: [
new VueLoaderPlugin()
]
};

module.exports = config;

上面配置好了之后还差最后一步,就是用webpack来执行配置跑项目,在scripts里面加上build:

"build": "webpack --config webpack.config.js"

  1. 执行npm run build来打包项目到dist下面的vendor.build.js:

这个时候会看到我们的项目中多了个dist,就是我们打包好的项目,这一步就省去了我们很多的http请求,达到更优化的效果。

在打包这一过程中,如果出现了打包失败,检查完问题后再次打包,如果显示的是打包失败,那么请删了之前打的包,重新build就会好了

三、运行项目
  1. 现在项目已经打包好了,接下来开始运行我们的项目,先建立一个属于我们的开发模式,这里需要使用webpack-dev-server来启动我们的webpack.config.js,进而运行我们的项目。使用它的东西第一步就是要安装npm i webpack-dev-server,再往scripts里面加上这个"dev": "webpack-dev-server --config webpack.config.js"

我们会看到有两个webpack.config.js,但是我们现在安装的是我们开发环境需要用到的,接下来增加一些开发模式需要用到的webpack的配置,这些配置我会逐步分析:

  1. webpack的编译目标是web项目,所以我们要target: 'web',放在全局的webpack的配置里面

  1. 需要配置一个环境变量来区分我们的生产环境和开发环境,输入dos命令npm i cross-env,在打包和运行之前都加上环境变量标识:
    "build": "cross-env NODE_ENV=production webpack --config webpack.config.js",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js",

个人习惯:喜欢运行start,所以把run dev替换掉了:"start": "npm run dev"
效果如下:

  1. 再从webpack的配置里加个判断,如果是开发环境,就把我们的webpack服务放进去:

首先用一个变量代表是开发环境:const isDev = process.env.NODE_ENV === 'development';在package.json scripts里面设置的生产和开发环境的环境变量都存在于cross-dev,我们设置脚本的时候启动的环境变量全都存在于process.env里面,这样我们在之后可以随意调用它

然后在最下面给module.exports赋值之前,加个判断:

if (isDev) {
config.devServer = {
port: 8088, // webpack服务需要监听的端口号
host: '0.0.0.0', // 可以通过本机内网ip访问,这样别人也可以访问,手机也可访问,如果设置成localhost则不然
overlay: {
errors: true // 这个可有可无,webpack编译出现的错误会出现在网页中,便于更改
}
};
}

上述代码中的配置项我们在webpack官网中都可以看得到,每一步的原因我已在后面加了相关注释。

  1. 引入webpack,以便之后用webpack的插件,下面会用到DefinePlugin这个插件(ps:做vue或react的项目必须用到的,这些项目都会根据环境来区分打包)
    const Webpack = require('webpack');

用法和之前的一样,所有的插件都是需要引入并创建实例这一过程;下面根据之前配置好的环境变量在webpack编译的过程中,对写的js代码都会判断环境,根据不同环境对代码进行打包(我们只想要”development”,所以外面会加上单引号),代码如下:

new Webpack.DefinePlugin({
'process-env': {
NODE_ENV: isDev ? '"development"' : '"production"'
}
})

  1. 这也是最后一步,我们到现在为止还没有一个网页入口,先安装一个html-webpack-plugin,同样的引入配置好了,运行一下项目就ok了

  1. 项目是能运行了,但是我们每次更新DOM的时候,页面就得刷新,在这里扩展几个小tip:

webpack有个支持热加载功能的插件HotModuleReplacementPlugin,再通过vue-loader读取vue的组件,在devServer里面配置一个hot: true,就形成了热加载;

还一个是映射工具devtool,使用source-map做映射,将我们压缩文件中的代码映射回源文件中的原始位置的方法,更轻松调试,谷歌和火狐都已经支持,文件大效率低,导致webpack编译慢,而eval解析出来的会很乱,二合一是webpack提出来的有效的方法;

在CLI下的devServer下还有一个compress是用在所有服务端gzip 压缩,这个在Yahoo雅虎军规上有提到;

更多的好用的插件就去webpack官网了解吧

如果是自己建的html的小伙伴就可以在html-webpack-plugin里面配置它,之后再把带有id是app的div放进html里面,在app.vue里面渲染的dom就会生成在html中:

用完了这个webpack我感觉棒极了,以后项目必备品!

参考☟☟☟:
https://blog.csdn.net/c_kite/article/details/71279853
https://juejin.im/post/5acd890d6fb9a028d043ca15
https://juejin.im/post/5abef5e96fb9a028e33b9035
webpack官网

如果喜欢本文的话单击爱心加关注谢谢O(∩_∩)O~

本文的所有内容均是一字一句敲上去的,希望大家阅读完本文可以有所收获,因为能力有限,掌握的知识也是不够全面,欢迎大家提出来一起分享!谢谢O(∩_∩)O~

欢迎访问我的GitHub,喜欢的可以star,项目随意fork,支持转载但要下标注;
欢迎光临个人主页

等一下( •́ .̫ •̀ ),我还有最后一句话:
我爱你,
可我们总是用最恶毒的话去伤害最爱的人,
然后再用最深的忏悔去挽回,
感情就在这样的循环里撕扯和消磨,
慢慢变的无迹可寻了,
我们就这样在嘶吼里告别,
就像那些美好从未发生,
一切都会消失的,
感情也是,
一切都是需要守护的,
感情尤其是,
再见…