一、什么是webpack
静态模块打包工具
- webpack,将所有的前端资源文件(js/json/css/img/sass...)都会作为模块处理。它根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
- 处理模块间的依赖关系,让我们可以模块化开发,
- grunt/gulp/webpack---打包工具,打包:打包合成一个或多个包,转化成浏览器可以识别的代码
( 自己的理解:很多文件可能浏览器不支持,不能直接放在服务器,需要通过一些工具进行打包转换,生成浏览器可以识别的可以执行的代码 )
和gulp对比
二、安装
- 依赖于node,安装node。
- 安装webpack
#全局安装
npm install webpack@版本号 -g
#局部安装
cd 对应目录
npm install webpack@版本号 --save-dev
三、基本使用
3.1.开发
src--开发文件夹
/*****************mathUtils.js****************/
function add(num1,num2) {
return num1+num2
}
function mul(num1,num2) {
return num1*num2
}
//commonJS的模块化思想
module.exports={
add,
mul
};
/*******************info.js****************/
//使用ES6的模块化的规范
export const name="HHHH";
export const age="12";
export const height="162";
const message="你好呀";
export default message;
/*******************main.js****************/
//1.使用commonJS的模块化规范
const {add,mul}=require('./mathUtils');
console.log(add(20,30));//50
console.log(mul(20,30));//600
//2.使用ES6的模块化的规范
import m,* as info from "./info"
console.log(info.name,info.age,info.height);//HHHH 12 162
console.log(m);//你好呀
3.2.打包
命令行webpack-cli工具,全局安装:
#安装。-g,当前项目需要用,其他项目也需要用
npm install webpack-cli -g
#使用
webpack 需要打包的文件 打包输出的文件
dist--打包的文件夹
#把文件./src/main.js打包到./dist/bundle.js文件
webpack ./src/main.js ./dist/bundle.js
3.3.运行
index.html--运行的页面
<!--只要引入打包过的文件-->
<script src="./dist/bundle.js"></script>
四、配置
4.1.webpack配置
webpack.config.js--配置文件
const path=require('path')
module.exports={
entry:'./src/main.js'//入口
output:{//出口
/*
是要一个绝对路径,要动态获取路径
resolve:可以拼接
__dirname:node上下文中的全局变量,当前webpack.config.js所在的路径
*/
path:path.resolve(_dirbame,'dist'),
filename:'bundle.js'
}
}
package.json--npm init 初始化项目时产生
- devDependencies-----开发时依赖;
- dependencies------运行时依赖(打包完还需要用的话,放这)
4.2.使用局部webpack
- 只要终端(如cmd,webStorm的Terminal)中敲命令的用的都是全局。命令行:
webpack *****
- 具体项目中,项目会依赖特定版本的webpack。全局中的版本和项目中的webpack版本可能不一致,因此要使用局部。
- 下载局部的webpack。
npm install webpack@3.6.0 --save-dev
- vue-cli3中。webpack配置文件已被隐藏。
- 启动执行打包:
.\node_modules\.bin\webpack
- package.json中配置定义启动执行打包:
"build": "webpack"
- 执行脚本会优先去本地找,找不到再用全局
"scripts": {
"build": "webpack"
}
#配置package.json了后运行
npm run build
五、loader
5.1.什么是loader
- 没有做依赖不会打包
- 主要用webpack来处理我们写的js代码,并且webpack会自动处理js之间相关依赖。
- 但是开发中不仅仅有基本的js代码处理。我们也需要加载css、图片,也包括一些高级es6、TypeScript转成ES5代码,将scss、less转成css,将jsx、.vue文件转成js文件
- 对于webpack本身的能力来说。这些转化是不支持的,因此要给webpack扩展对应的loader就可以实现
5.2.css文件处理
/*在src文件夹下添加css/normal.css文件,在main.js中添加依赖,并打包*/
/*******************main.js****************/
//3.依赖css文件
require('./css/normal.css');//直接打包会报错,webpack本身的能力处理不了
- 需要下载配置css-loader、style-loader
css-loader
- npm install css-loader --save-dev
- 负责将css文件进行加载,不负责帮你解析,也不负责帮你把css放在html里帮你生效
style-loader
- npm install style-loader --save-dev
- 负责将样式添加到DOM中,会生成style标签
webpack.config.js配置css
module:{
rules:[
{
test:/\.css$/,//匹配
use:['style-loader','css-loader']//使用多个loader时,是从右向左
}
]
}
5.3.less文件处理
/*在src文件夹下添加css/special.less文件,在main.js中添加依赖,并打包*/
/*******************main.js****************/
//4.依赖less文件
require('./css/special.less');//直接打包会报错,webpack本身的能力处理不了
- 需要下载配置less 、 less-loader
less
- npm install less --save-dev
- 将less文件进行转换为css文件
less-loader
- npm install less-loader --save-dev
- 内部调用less
webpack.config.js配置less
module:{
rules:[
{
test: /\.less$/,
// use: ['style-loader','css-loader', 'less-loader']
use: [{
loader: "style-loader" // 从JS字符串创建样式节点(负责将样式添加到DOM中)
}, {
loader: "css-loader" // 将CSS转换为CommonJS(将css文件进行加载)
}, {
loader: "less-loader" //将 Less 编译为 CSS
}]
},
]
}
5.4.图片文件处理
/*在src文件中添加图片文件 img/bg.png,并在normal.css中引入*/
/*src/css/normal.css*/
body{
background: url("../img/bg.png");
}
url-loader
- npm install url-loader --save-dev
- 将文件作为 data URI 内联到 bundle 中
- limit属性。如limit:8192,当图片小于8kb,对图片进行base64编码
file-loader
- npm install file-loader --save-dev
- 将文件发送到输出目录
- 当图片大于8kb,通过file-loader进行处理
webpack.config.js配置图片文件处理
module:{
rules:[
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
//当加载的图片,小于limit时(单位kb),会将图片编译成base64字符串形式
//当加载的图片,大于limit时(单位kb),会使用file-loader模块对图片进行加载
options: {
limit: 72680,
/*
图片文件处理-修改文件名称:
变量要用[]
[name]:图片本身的名字
[hash:8]:哈希8位
[ext]:原来的扩展名
*/
name:'img/[name].[hash:8].[ext]'
},
}
]
},
]
}
5.5.ES6语法的处理
babel-loader
- npm install -D babel-loader @babel/core @babel/preset-env webpack
module:{
rules:[
{
test: /\.js$/,
//exclude:排除
//include:包含
//只需要转化src这个文件,这个node_modules|bower_components文件不需要转化
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
//配置, ['@babel/preset-env']会去找babel-preset-env文件,但是我们没有下
presets: ['@babel/preset-env']
}
}
},
]
}
5.6.配置Vue
安装vue
- npm install vue --save ( 运行时也需要依赖,运行依赖,所以不需要加-dev )
el和template
- el:指定Vue要管理的DOM,可以帮助解析其中的指令、事件监听。
- template:Vue实例中的template模板的内容,会替换掉挂载的对应的el的模板。
- 不频繁的修改index.html
内容直接在template中:
/*******************src/main.js****************/
//5.使用Vue进行开发
import Vue from 'vue'
new Vue({
el: '#app',
template: `
<div>
<h2>{{message}}</h2>
</div>
`,
data(){
return{
message: 'hello webpack'
}
}
});
将template的内容抽离到app.js文件中成组件:
/*******************src/main.js****************/
//5.使用Vue进行开发
import Vue from 'vue'
import App from "./vue/app.js"
new Vue({
el: '#app',
template: '<App/>',
components:{
App
}
});
/*******************src/vue/app.js****************/
export default {
template: `
<div>
<h2>{{message}}</h2>
<button @click="btnClick">按钮</button>
</div>
`,
data(){
return{
message: 'hello webpack'
}
}
};
template的内容抽离到App.vue文件中成组件:
/*******************src/main.js****************/
//5.使用Vue进行开发
import Vue from 'vue'
import App from "./vue/app.js"
new Vue({
el: '#app',
template: '<App/>',
components:{
App
}
});
<!------------------index.html------------------->
<div id="app"> </div>
<!------------------src/vue/App.vue------------------->
<template>
<div>
<h2 class="title">{{message}}</h2>
<Cpn></Cpn>
</div>
</template>
<script>
import Cpn from './Cpn';
export default {
name: "APP",
components:{
Cpn
},
data(){
return{
message: 'hello webpack'
}
}
}
</script>
<style scoped>
.title{
color: blueviolet;
}
</style>
<!----------------src/vue/Cpn.vue------------------->
<template>
<div>
<h2> {{name}}</h2>
</div>
</template>
<script>
export default {
name: "Cpn",
data() {
return{
name:'cpn组件name'
}
}
}
</script>
.vue文件封装的处理
- npm install vue-loader vue-template-compiler --save-dev
- vue-loader:.vue文件的加载;
- vue-template-compiler:.vue文件的编译
打包项目出错错误
- runtime-only:代码中,不可以有任何的template
- runtime-complier:代码中可以有template,因为有compiler可以用于编译template
webpack.config.js中配置vue
module:{
rules: [
{
test: /\.vue$/,
//vue-loader必须配置另一个插件,或用低版本,改package.json"vue-loader": "^13.0.0",
use:['vue-loader']
}
]
},
resolve:{
//配置省略后缀
extensions:['.js','.vue','.css'],
//alias别名
alias:{
// 当import Vue from 'vue' 时,先看下vue有没有指向具体的某个文件夹,这样就不会按默认的方式找某个文件了,会按照文件夹的路径去找
'vue$':'vue/dist/vue.esm.js'//选的时runtime-compiler而不是runtime-only
}
}
六、webpack的plugin
6.1.认识plugin
- 给打包文件一些说明信息
6.2.添加版权
/**********webpack.config.js**********/
//依赖webpack
const webpack=require('webpack');// 用于访问内置插件
module.exports={
plugins:[
new webpack.BannerPlugin('最终版权HHHH'),//dist/bundle.js下会多版权信息
],
};
6.3.打包html
- 当前的index.html是放根目录下,但是发布的是dist文件夹,所以应该将index.html文件打包到dist文件夹中
- npm install html-webpack-plugin --save-dev
/**********webpack.config.js**********/
const HtmlWebpackPlugin=require('html-webpack-plugin')
module.exports={
output:{//出口
path:path.resolve(__dirname,'dist'),
filename:'bundle.js',
// publicPath:'dist/'
},
plugins:[
new HtmlWebpackPlugin({
template: 'index.html' //根据这个模板生成dist中的index
}),
],
};
//index.html文件不需要导入js,只要<div id="app"> </div>
6.4.js压缩
- npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
/**********webpack.config.js**********/
const UglifyjsWebpackPlugin=require('uglifyjs-webpack-plugin')
module.exports={
plugins:[
new UglifyjsWepackPlugin(),
],
};
七、搭建本地服务器
- webpack-dev-server
- npm install --save-dev webpack-dev-server@2.9.1
- webpack.config.js配置
/**********webpack.config.js**********/ devServer:{ contentBase:'./dist', inline:true }
- 没有在全局安装webpack-dev-server,只在局部安装,没有配置又在终端执行时,使用路径命令
.\node_modules\.bin\webpack-dev-server
- package.json配置
- --open表示运行程序不需要再自己点链接就自己运行
- npm run dev运行
"scripts": {
"dev": "webpack-dev-server --open"
}
八、配置文件的分离
- 开发阶段不建议使用UglifyjsWepackPlugin进行js压缩,一旦压缩,在浏览器中不好调试,发布才需要;
- 编译打包发布时,这个devServer:{contentBase:'./dist',inline:true }不需要,只在开发阶段需要 , 所以要做webpack.config.js配置文件分离
- 新建build文件,build文件下新建 base.config.js、dev.config.js 、 prod.config.js
- 开发:base.config.js+dev.config.js
- 生产:base.config.js+prod.config.js
- 文件合并: npm install webpack-merge --save-dev
/**********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 UglifyjsWepackPlugin=require('uglifyjs-webpack-plugin');
const webpackMerge=require('webpack-merge');
const baseConfig=require('./base.config');
module.exports=webpackMerge(baseConfig,{
plugins:[
new UglifyjsWepackPlugin()
],
});
/**********base.config.js **********/
const path =require('path');
const webpack=require('webpack');
const HtmlWebpackPlugin=require('html-webpack-plugin');
module.exports={
entry:'./src/main.js',//入口
output:{//出口
path:path.resolve(__dirname,'../dist'),//是要一个绝对路径,要动态获取路径 resolve:可以拼接 __dirname:node上下文中的全局变量,当前webpack.config.js所在的路径
filename:'bundle.js',
// publicPath:'dist/'
},
module:{
rules: [
{
//匹配
test: /\.css$/,
//css-loader只负责将css文件进行加载,不负责帮你解析,也不复杂帮你把css放在html里帮你生效
//要再安装一个style-loader
//style-loader负责将样式添加到DOM中
//使用多个loader时,是从右向左
use: [ 'style-loader','css-loader' ]
},
{
//匹配
test: /\.less$/,
// use: ['style-loader','css-loader', 'less-loader']
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
},
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'url-loader',
//当加载的图片,小于limit时,会将图片编译成base64字符串形式
//当加载的图片,大于limit时,会使用file-loader模块对图片进行加载,直接安装就好>npm install file-loader --save-dev
options: {
limit: 200, //img/name 打包出来的名字直接叫name.png; img/name/ img文件夹下创建name文件夹 变量要用[],ext原来的扩展名
name:'img/[name].[hash:8].[ext]'
},
}
]
},
{
test: /\.js$/,
//exclude:排除
//include:包含
//只需要转化src这个文件,这个node_modules|bower_components文件不需要转化
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
//配置, ['@babel/preset-env']会去找babel-preset-env文件,但是我们没有下
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
//vue-loader必须配置另一个插件,或用低版本,改package.json"vue-loader": "^13.0.0",
use:['vue-loader']
}
]
},
resolve:{
//配置省略后缀
extensions:['.js','.vue','.css'],
//alias别名
alias:{
// 当import Vue from 'vue' 时,先看下vue有没有指向具体的某个文件夹,这样就不会按默认的方式找某个文件了,会按照文件夹的路径去找
'vue$':'vue/dist/vue.esm.js'//选的时runtime-compiler而不是runtime-only
}
},
plugins:[
new webpack.BannerPlugin('最终版权HHHH'),
new HtmlWebpackPlugin({
template: 'index.html' //根据这个模板生成dist中的index
}),
],
};
- package.json配置
{
"scripts": {
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --open --config ./build/dev.config.js"
},
}