webPack
- 什么是webPack,从本质上讲webPack是一个现代的JavaScript应用的静态模块打包工具
- 前端模块化的一些方案:AMD、CMD、CommonJS、ES6
- webPack其中一个核心就是让我们可能进行模块化开发,并且会帮助我们处理模块间的关系
- 而且不仅仅是JavaScript文件,我们的css、图片、json文件等等在webPack中都可以被当作模块来使用
- 将webPack中的各种资源模块进行打包合并成一个或多个包(bundle)
- 在打包的过程中,还可以对资源进行处理,比如压缩图片,将scss文件转成css,将ES6语法转成ES5语法,将typescript转成javascript等等操作
grunt/gulp的对比
-
grunt/gulp的核心是Task
我们可以配置一系列task,并且定义task要处理的任务
之后让grunt/gulp来一次执行这些task,而且让整个流程自动化
所以grunt/gulp也被称为前端自动化任务管理工具 -
我们来看一个gulp的task
下面的task就是将src下面的所有js文件转成ES5的语法
并且最终输出到dist文件夹中 -
什么时候用grunt/gulp
如果你的工程模块依赖非常简单,甚至是没有用到模块化的概念
只需要进行简单的合并、压缩,就使用grunt/gulp即可
但是如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的webpack了 -
grunt/gulp和webpack有什么不同
grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心
webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能
webpack的安装
必须依赖node环境
node为了可以正常执行很多代码,必须其中包含各种依赖的包npm工具(node packages manger)
- 安装webpack首先需要安装node.js,Node.js自带了软件包管理工作npm
- 查看自己的node状态, node -v
- 全局安装webpack: npm install webpack@3.6.0 -g
- 局部安装webpack:
cd 到对应的目录
npm install webpack@3.6.0 --save-dev
文件和文件夹解析
dist文件夹:用于存放之后打包的文件
src文件夹:用于存放我们写的源文件
- main.js :项目的入口文件
- index.html: 浏览器打开展示的首页面
- package.json: 通过npm init生成的,npm包管理的文件(暂时没有用上,)
模块化
导入和导出
早期
//aaa.js 导出
moduleA = (function(){
obj = {};
var flag =false;
function sum(){}
obj.flag = flag;
obj.sum = sum;
return obj
})()
//bbb.js
console.log(moduleA.flag )//相当于导入
commonjs
//aaa.js文件
//导出
modlue.exports ={
flag:true,
test(a,b){}
}
//导入
let {test,demo,flag}=require('./aaa.js')
es6
export flag =true;
export function sum(){}
export class person{}
或
export{flag,sum}
import{flag,sum}from './aaa.js'
直接webpack不用指明路径的配置
需要在工程路径下简历一个文件webpack.config.js文件,配置;
- entry: 文件的输入路径
- output:文件的输出路径
const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: "bundle.js",
},
}
path是一个node库,如果需要是用需要执行npm init
package.json中定义启动
我们可以在package.json中的scripts中定义自己的执行脚本
简化执行命令,在scripts对象中配置
如:“build”:“webpack”
{
"name": "meetwebpack",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build":"webpack"
},
"author": "",
"license": "ISC"
}
- 在执行npm run build指令时,会优先使用本地的webpack
- 在使用webpack时使用的是全局的webpack
安装本地webpack: npm install webpack@3.6.0 --save-dev
–save-dev则会把信息记录到devDependencies中,devDependencies中记录的是项目在开发过程中需要的一些文件,在项目最终运行时是不需要的;也就是说我们开发完成后,最终的项目中是不需要这些文件的
是在开发时依赖,运行时不依赖
–save则会把信息记录到Dependencies中,项目运行时依赖的文件
loader
官方网址:https://webpack.js.org/
中文网址:https://www.webpackjs.com/
查看loader verson网址:https://www.npmjs.com/
在开发中我们不仅仅有基本的js代码处理,我们也需要加载css,图片,也包括一些高级的将es6转陈es5的代码,将typescript转成es5代码,将scss,less转成css,将.jsx .vue文件转成js文件等。对于webpack来说,本身能力不足,就需要对应loader去处理
使用多个loader时,是从右向左
使用步骤:
- 通过npm 安装需要使用的loader
- 在webpack.config.js中modules关键字下进行配置
问题:
(node:66772) UnhandledPromiseRejectionWarning: TypeError: this.getResolve is not a function
css-loader 和style-loader版本过高,需要降低版本
css-loader
安装
安装的版本是最新的,可能版本会过高
npm install --save-dev css-loader
file.js
import css from 'file.css';
webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
}
test: /.css / : 正 则 表 达 式 , 转 义 , / :正则表达式,\ 转义, /:正则表达式, 转义,结束标志,匹配所有css文件
css-loader只负责加载css文件,但是不负责将css具体样式嵌入到文档中
style-loader
安装
npm install style-loader --save-dev
安装的版本是最新的,可能版本会过高
用法
file.js
import style from './file.css'
webpack.config.js
{
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" }
]
}
]
}
}
less-loader
url-loader
当图片的大小小于设置的最大值,需要安装file-loader, npm run build之后,会在dist中生成一个图片文件
在安装完file-loader之后,不需要拷贝它的配置。生成的图片在dist文件夹下,但是我们设置的background的url是在当前路径下,会导致文件找不到。这个时候需要设置路径。设置了publicPath之后,设置了url都会先去dist文件夹下找。
生成的文件名是hashcode数字,没有辨识度,需要优化了,[name]原来图片的名字,hash:8 新生成的hashcode的前8位,ext是原文件名的后缀。
Es6转成Es5
如果你阅读webpack打包的js文件,发现写的ES6语法并没有转成ES5,那么就意味着并没有转成ES5,
指令
npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
配置webpack.config.js
exclude: /(node_modules|bower_components)/:表示排除node_modules或bower_components文件内的js文件
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
重新打包,查看bundle.js文件,发现其中的内容变成了ES5的语法
引入vue.js
我们希望在项目中使用vuejs,那么必然需要对其依赖,所以需要先进行安装,因为我们需要后续在实际项目中也会使用vue的,所以并不是开发依赖
npm install vue --save
问题:bundle.js:1329 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
这个错误说的是我们使用的runtime-only版本的vue。
vue有runtime-only(运行)和runtime-compile(编译)
- runtime-only: 不可以有任何的template
- runtime-compile可以用于编译template
修改如下配置
默认是使用vue.runtime.main.js
el和template的区别
正常运行之后,考虑另外一个问题:
- 如果我们希望将data中的数据显示在界面中就必须修改index.xml
- 如果我们后面自定义了组件,也必须修改index.xml来使用组件
- 但是html模板在之后的开发中,并不希望手动的来频繁修改,是否可以左到呢?
定义template属性:
- 在前面的Vue实例中,我们定义了el属性,用于和index.html中的#app进行绑定,让vue实例之后可以管理它其中的内容
- 这里,我们可以将div元素中的{{mesage}}内容删掉,只保留一个基本的id为div的元素
- 但是如果我们依然希望在其中显示{{message}}的内容,应该怎么处理呢
- 我们可以再定义一个template属性
第一版 :定义组件,结构如下;
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
<script src="./dist/bundle.js"></script>
</body>
</html>
main.js
import Vue from 'vue'
const App = {
template:`
<div>
<h2>{{message}}</h2>
</div>
`,
data: function () {
return {
message: 'code why',
}
}
}
new Vue({
el:'#app',
template:'<App/>',
components:{
App
}
})
第二版升级,再将component封装在一个文件内app.js
export default {
template: `
<div>
<h2>{{message}}</h2>
</div>
`,
data: function () {
return {
message: 'code why ddd',
}
}
}
然后在main.js中import
import Vue from 'vue'
import App from './js/app'
new Vue({
el:'#app',
template:'<App/>',
components:{
App
}
})
终极版
一个组件是以一个js对象的形式进行组织,使用的时候非常不方便
- 一方面编写template模块非常的麻烦
- 如果有样式的化,我们写在那里比较合适
安装vue
npm install vue-loader vue-template-compiler --save-dev
配置
{
test: /.vue$/,
use: ['vue-loader']
},
注意:
版本问题,在14以后需要plugin
现在安装的版本
"vue-loader": "^13.1.0",
"vue-template-compiler": "^2.6.12",
vue文件是的template和js代码分离
<template>
<div>
<h2 class="title">{{message}}</h2>
<p>{{name}}</p>
</div>
</template>
<script>
export default {
name: "App",
data: function () {
return {
message: 'code why ddd',
name:'liu yun dddddd ',
}
}
}
</script>
<style scoped>
.title{
color: red;
}
</style>
认识plugin
plugin是什么?
- plugin是插件的意思,通常是对某个现有的架构进行扩展
- webpack中的插件,就是对webpack现有功能的各种扩展,比如打包优化,文件压缩等等
loader和plugin的区别
- loader主要用于转换某些类型的模块,它是一个转换器
- plugin是插件,它是对webpack本身的扩展,是一个扩展器
plugin的使用过程
- 通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装)
- 在webpack.config.js中的plugins中配置插件
添加版权的plugin
该插件名字是BannerPlugin,属于webpack自带的插件。
按如下方式修改webpack.config.js中的文件:
plugins:[
new webpack.BannerPlugin('版权归UIH所有'),
]
打包html的plugin
目前我们的index.html文件是存放在项目的根目录下的
-
我们知道,在真是发布项目时,发布的dist文件夹中的内容,但是dist文件夹如果没有index.html文件,那么打包的js文件就没有意义。
-
所以,我们需要将index.html 文件打包到dist文件夹中,这个时候就要用到HtmlWebpackPlugin插件。
HtmlWebpackPlugin插件可以为我们做这些事情:
-
自动生成一个index.html文件 (可以指定模板来生成),可以让dist文件下生成的index.html中有id=“app”
-
将打包的js文件,自动通过script标签插入到body中,如图
安装HtmlWebpackPlugin插件
npm install html-webpack-plugin --save-dev
版本:
"html-webpack-plugin": "^3.2.0",
注意;
-
webpack 是3.6,所以html-webpack-plugin也是差不多3.多的
-
调试的时候,用dist文件夹下的index.html
使用插件
- 这里的template表示根据什么版本来生成index.html
- 另外,我们需要将删除之前在output中添加的publicPath属性
- 否则,插入的src可能会有问题
js压缩的Plugin
在项目发布之前,我们必然需要对js等文件进行压缩处理
- 这里,我们就对打包的js文件进行压缩
- 我们这里使用一个第三方的插件uglifyjs-webpack-plugin,并且版本号指定1.1.1,和cli2保持一致
npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
-
修改webpack.config.js文件,使用插件
-
查看打包后的bundle.js文件,是已经被压缩过了
搭建本地服务器
- webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果
- 不过它是一个单独的模块,在webpack中使用之前需要先安装它
- webpack-dev-server的版本跟webpack对应关系
npm install --save-dev webpack-dev-server@2.9.1
- devserver也是作为webpack中的一个选项,选项本身可以设置如下属性:
-
contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist
-
port:端口号
-
inline:页面实时刷新
-
historyApiFallback:在SPA页面中,依赖HTML5的history模式
-
webpack.config.js文件配置修改如下
-
我们可以再配置另外一个scripts:–open参数表示直接自动打开浏览器
-
配置的分离
有些配置需要在开发的使用,有些在发布的时候的时候使用,这样就需要将配置进行分离
新建3个文件
- base.config.js 公用配置
- dev.config.js 开发配置
- prod.config.js 生产配置
安装插件
最新版本有问题
npm install webpack-merge@3.0.0 --save-dev
合并config
dev.config.js
const WebpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')
module.exports = WebpackMerge(baseConfig,{
devServer:{
contentBase:'./dist',//指定监听的文件夹
inline:true,//页面实时刷洗
}
})
prod.config.js
const WebpackMerge = require('webpack-merge')
const baseConfig = require('./base.config')
module.exports = WebpackMerge(baseConfig, {
plugins:[
new UglifyjsWebpackPlugin()
],
})
修改package.json配置
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
},
问题
- [Vue warn]: Cannot find element: #app
打包错误信息:
这是因为你的js在html页面头部引入的原因,自定义js文件要最后引入,因为要先有元素id,vue才能获取相应的元素。
<script src="./dist/bundle.js"></script> //要放到最后
2.ERROR in ./node_modules/css-loader/dist/cjs.js!./node_modules/less-loader/dist/cjs.js!./src/css/special.less
Module build failed: TypeError: this.getOptions is not a function
3.(node:86832) UnhandledPromiseRejectionWarning: TypeError: loaderContext.getResolve is not a function
都是less-loader和less的版本太高,修改为如下版本
4.(node:66772) UnhandledPromiseRejectionWarning: TypeError: this.getResolve is not a function
css-loader 和style-loader版本过高,需要降低版本
5.bundle.js:1329 [Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.**
这个错误说的是我们使用的runtime-only版本的vue。
vue有runtime-only(运行)和runtime-compile(编译)
- runtime-only: 不可以有任何的template
- runtime-compile可以用于编译template
修改如下配置