1、为什么要有模块化?
在团队开发的前端项目中很难避免的问题之一就是如何避免变量的重名问题,ES5时在前端开发中一般会使用闭包的形式避免变量名称重复。每个作用域范围内的js代码都能称为是一个模块,ES6中依然存在变量名称问题,但是已经得到了更好的解决。
常见的模块化规范:CommonJS、AMD、CMD、ES6中的Modules.但是目前的浏览器只支持ES6模块化规范。
模块化的两个核心思想:导入和导出。
2、ES6中的模块化
如上图,有三个js文件分别是xm.js,xh.js,xm2.js和一个html文件:index.html,此时由于type=module,三个js文件变成了三个独立的模块,此时,三个js文件中的变量和数据都不能互相访问,这肯定不是我们想要的,所以我们需要将三个模块中的变量导出,其他模块在使用时导入对应的模块就可以了,导出用export,导入用import.
2.1 export、import
如上图,这样的话xm2.js文件就能使用xm.js文件中的变量了。还能在定义变量的同时导出:
export let name = '小明'
export let age=12
export let flag = true
export function sum(num1,num2){
return num1+num2
}
3、webpack
3.1 认识webpack
有些文件,例如.sass、.cjs文件是浏览器不支持的,因此需要将这些文件转换成浏览器支持的文件如.js、.css文件等。这个转换的工具就是webpack。使用webpack工具进行底层支持我们可以使用前面提到的CommonJS、AMD、CMD等前端模块化规范,也就是说在开发中可以写这些规范的代码,但是经过webpack打包后浏览器可以识别并处理这些代码。除此之外webpack还能帮助我们处理模块之间的依赖,减少频繁的导入和导出操作。当然webpack除了模块化开发管理还具有文件压缩合并、预处理等很多功能,但是最主要的是它的模块化开发管理功能。
3.2 webpack安装
要想让webpack干活就需要为它提供能干活的环境,就像Java中的JDK和JRE,webpack依赖的环境是node环境,node环境也是依赖很多包的,通常我们在安装node环境的时候会自动安装一个叫npm(node packages manager)的工具,这个工具的作用仅仅是帮助我们管理node环境中的各种包而已。
下载地址:下载 | Node.js 中文网 (nodejs.cn)
下载完成后在命令黑窗中输入** node -v** 查看是否安装成功,安装成功的话显示node版本.
下载完node之后在小黑框中输入:**npm install webpack@3.6.0 -g 点击回车安装webpack,安装结束后输入webpack -v **如果能显示当前的webpack版本则表示当前的webpack安装成功了!
完成上述安装后就能使用webpack对我们的项目进行打包了。
3.3 webpack的起步
3.3.1 使用webpack管理项目的基本流程。
在以后的项目中我们将源码放在src目录中,项目打包后的文件放到dist文件夹中,到时候只将dist文件夹发布到服务器上面就行了。也就是下图所示:
首先是js文件的导出和导入,这里使用CommonJS模块化规范进行导入和导出:
那问题来了,该如何打包呢?需要在终端中执行以下命令:
cd v2-webpack的使用:该命令表示进入到v2-webpack的使用文件夹。
webpack ./src/main.js ./dist/bundle.js:表示将当前项目下的main.js文件使用webpd打包到当前项目下的dist文件中的bundle.js文件。
回车后便能看到bundle.js文件的生成过程,在dist文件中可见该文件已生成:
然后便可在index.html文件中使用bundle.js文件了:
代码运行结果:
上述流程就是前端项目编写、打包的基本过程了但是除了上述基本流程之外还涉及到很多的细节以及优化策略。需要注意的是index.html文件是放到项目根路径下的而不是放在src文件下。
3.3.2 webpack.config.js文件和package.json文件的使用
在(1)中我们通过在终端使用webpack ./src/main.js ./dist/bundle.js命令将js文件打包,但是这么写比较繁琐,因此我们希望使用webpack命令就能实现打包,这样的话就需要在某个地方告诉webpack我要将什么文件打包到哪里, 所以我们需要在配置文件(webpack.config.js)中配置相关信息告诉webpack文件的打包方式。配置如下:
/*在node包中导入path包*/
const path = require('path')
module.exports= {
/*入口,就是main.js*/
entry:'./src/main.js',
output:{
/*路径,__dirname保存的就是当前文件webpack.config.js所在的路径,'dist'表示会在当前路径上拼接dist*/
path:path.resolve(__dirname,'dist'),
/*文件名*/
filename:'bundle.js'
},
/*出口*/
}
这里使用了path这个包,这个包是npm管理的,因此需要在webpack中使用npm加载初始化包,建议在刚开始搭建项目时就将node相关的包加载好:
执行完上述指令后会生成个json文件,叫package.json
该文件中其实是关于我们项目的一些i信息,该文件是node依赖的门口,也就是说我们只要使用webpack管理项目就要使用npm init 指令加载一些包,然后生成package.json文件。配置完webpack.config.js文件之后在终端只需要使用webpack指令就能将main.js文件打包到dist文件中。
综上:我们其实就主要干了一件事就是使用webpack指令将main.js(入口文件)打包到dist文件中。
当前我们项目依赖webpack是全局的,但是在一些项目中会单独给项目安装一个webpack,如果我们直接在终端使用webpack命令的话
那么会将项目中的所有的配置都将按照全局的webpack打包,那么就很容易出错,所以为了规范化开发,我们需要在当前项目中安装webpack:
安装好项目的webpack后package.json文件和项目都出现了变化:
那现在我们在终端中执行webpack命令的话是不是就是使用的本项目中的webpack呢?不是,只要是在终端 不管是在webstorm这个开发软件还是在小黑窗中使用该命令使用的webpack都是全局的,那我要如何才能使用本项目中的webpack呢?这就需要在package.json中添加webpack命令的映射:
这样的话只需要在webstorm终端输入:**npm run build **指令 就能使用本项目中的webpack对项目进行打包。使用这种方式的好处就是,首先npm首先会去本项目中寻找webpack,本项目中没有的话再去全局寻找webpack.
4、webpack中loader的使用
前面介绍了webpack,使用webpack主要是模块化开发我们的代码并且webpack还会自动处理模块之间的依赖。但是前端项目中还需要其他文件,例如css、图片,也包括将一些高级的ES6语法转化成ES5语法、vue文件转换成js文件等,对webpack本身来讲这些转化他本身是不支持的此时就需要给webpack安装扩展功能loader。
4.1 css-loader和style-loader的使用
不同的loader负责处理不同的格式,需要某个loader时要使用npm将loader下载下来,然后在webpack.config.js文件中的modules关键字下进行配置。
假设项目中存在css文件:
我们知道要想使该css文件生效的话需要在index.html文件中中引用该css文件,但是需要注意的是大型项目中的css样式有上百个难道需要我们一个一个引用吗?当然不是我们需要将css文件模块化引入到打包文件** bundle.js文件中。但是在当前项目中入口文件main.js中没有引入css文件,所以使用指令npm run build **并不能将css文件打包到bundle.js文件中。只要将css模块引入到main.js文件中就能将css样式引用:
然后就要将main.js文件打包,那么webpack既然处理不了css文件,那处理css文件的loader是哪个呢?给出官网地址,可以在中文官网找到答案:
loaders | webpack 中文网 (webpackjs.com)
带你进去之后会有详情的下载步骤,这里要注意的是,在本项目中我的webpack版本是5.0.0。因为安装3.6.0的版本css loader 和style loader 安装不上。
4.2 less-loader的使用
less文件要想被项目加载就需要引入到项目的入口文件main.js中。本质上lessloader的作用是将less文件转换成css文件
/*引入less文件*/
require('./css/special.less')
使用指令npm install --save-dev less-loader less加载lessloader,然后在webpack.config.js文件中添加相关配置, 再进到项目中执行打包指令: ** npm run build,即可。**
4.3 url-loader、file-loader
在css文件中使用图片时也需要下载图片的loader,也就是url-loader@1.1.2,下载完后还需要在配置文件中添加相关配置:
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
/*当图片的大小小于limit(KB)时会使用url-loader将图片编译成base64的字符串形式*/
limit: 70000
/*当图片的大小大于limit时,会使用file-loader对图片进行加载。使用file-loader
* 不需要进行配置只需下载file-loader即可*/
}
}
]
}
]
}
然后需要进行重新打包:npm run build
运行index.html文件:
当图片的大小大于limitKB时需要加载file-loader@3.0.1,然后将文件重新打包。
4.4 babel-loader
转成ES5的原因是现在很多的浏览器不支持ES6的语法(chrom支持),为了让更多浏览器兼容项目,需要使用babel-loader,首先需要在配置文件中添加配置:
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
然后在终端使用指令:npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
然后重新打包运行,观察dist文件夹下面的bundle.js文件发现变成ES5的语法格式。
5、webpack中配置Vue
如果在项目中想使用vue的话需要添加vue的依赖,之前使用<scprit>标签引用的vue不是模块化管理的vue。在引入模块化思想之后需要使用npm安装:npm install vue@2.5.21 --save 因为整个项目都是使用vue所以不需要加--dev 然后在配置文件中添加resove属性:
resolve:{
alias:{
"vue$":'vue/dist/vue.esm.js'
}
}
完成上述的配置之后就能使用了:
6、el和template的区别
在实际的开发中index.html文件是不会修改的也就是说index.html文件只是负责引入bundle.js文件和编写vue实例挂载的对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--
vue挂载的对象
-->
<div id="app">
</div>
<!--
引入bundle.js文件
-->
<script src="./dist/bundle.js"></script>
</body>
</html>
如果相使用vue实例内部的数据的话该怎么写呢?需要写在vue的template和属性中。最后编译的时候会将index.html文件中的
替换成template中的内容:/*引入vue*/
import Vue from 'vue'
const app = new Vue({
el:"#app",
template:`
<div>
<p>{{message}}</p>
</div>
`,
data:{
message:"哈哈"
}
})
重新打包运行:
查看编译后的代码:
发现之前的
结论:vue实例中的template会在编译的时候替换el
但是假设vue实例中的template代码很多呢?写在template中就不合适了,就需要抽取。
也就是将模板抽取成模板对象,在vue实例中注册模板对象。代码如下:
/*组件*/
const APP = {
template:`
<div>
<p>{{message}}</p>
</div>
`,
data(){
return{
message: "KJHJADGFLASGKJHFLASJKDFHASKJDLFHLJKSADF"
}
}
}
/*引入vue*/
import Vue from 'vue'
const app = new Vue({
el:"#app",
template:'<APP/>',
/*注册组件*/
components:{
APP
}
})
进一步抽取,我们将组件抽取到转门写vue的文件夹vue中文件的名字叫app.js。
重新将项目打包运行即可。
但是在app.js中模板代码和js代码仍然 没有分离因此需要对模板再进行抽取。所以现在需要在vue文件夹下创建文件App.vue。但是在创建App.vue文件时需要加载loader文件:npm install vue-loader@13.0.0 vue-template-compiler@2.5.21 --save-dev
还要在配置文件中的module中添加相关配置如下:
在main.js文件中导入App.vue文件并打包运行即可。
注意:
7、vue终极使用
vue终极使用其实就是以后要将组件写到xxx.vue文件中并导出,在其他js文件中使用组件的时候只需要将组件导入即可。
8、plugin的使用
** 8.1 什么是plugin**
plugin是插件的意思主要用于对现有的某个插件进行扩展。webpack中的插件就是对webpack的功能进行扩展。
loader和plugin的区别在于loader是个格式转换器,是将浏览器不认识的格式转换为浏览器认识的格式,而plugin是插件是对webpack的扩展。
8.2 plugin的安装和配置
8.2.1、添加版权的plugin
8.2.2 HtmlWebpackPlugin
项目发布的时候是发布的dist文件夹里面的东西,但是dist文件夹中是没有index.html文件的。该插件的作用是将index.html文件发布到服务器上。此时就用到了HtmlWebpackPlugin插件。
HtmlWebpackPlugin插件可以为我们干哪些事情?
1.自动生成index.html文件(可以指定模板生成)
2.将打包的js文件,自动通过script标签插入到body中。
要想使用该插件需要先安装该插件:
插件安装完成之后需要修改配置文件webpack.config.js:
(1)导入依赖
(2) 在下面的module中的plugin对象中添加如下代码:
(3)程序打包
然后就能看到在dist文件夹中自动生成的index.html文件
此时在src下面的index.html文件中就不需要引入bundle.js文件了。但是模版也需要加载到dist文件夹中的index.html文件中。
因此需要在配置文件中添加如下:
(4)为dist文件下的index.html文件添加模板
重新打包后观察dist文件下的index.html文件会发现app模板被引入了。
8.2.3 uglifyjsWebpackPlugin
该插件是用来压缩bundle.js文件的。使用步骤和其他的插件是一样的。但是在开发阶段是不建议使用的。
(1)安装插件
(2)修改配置文件
(3)打包
查看bundle.js文件:
9、搭建本地服务器(实时刷新代码)
在之前编写代码的时候几乎每一步查看效果都需要我们重新打包并运行,webpack提供了解决方案,在项目没有发布之前先将项目保存到内存中,并监听代码,当代码发生修改的时候将修改的代码存储到磁盘中,在浏览器上运行的时候直接读取内存中的数据就行了。
(1)下载插件
(2)修改配置文件
(3)在webpack.json文件夹中配置当前项目运行指令
(4)在终端执行指令
然后写代码的时候都会实时刷新。
10、webpack配置文件的分离
配置文件的抽离是指将项目运行时的配置文件和项目发布时的配置文件分开。配置文件的分离在脚手架中会使用。
(1)新建文件夹build,在该文件夹下面创建如下三个js配置文件。
base.config.js文件:公共的配置文件。
dev.config.js文件:开发时使用的配置文件。
prod.config.js文件:生产时使用的配置文件。
(未完待续……)
版权归原作者 软件20-2张锦 所有, 如有侵权,请联系我们删除。