1.WebPack基础

1. 概述

1.1 Webpack功能与优势

预处理(TS,Less,Sass,ES6),解析成浏览器识别的css和js
解析文件之间的依赖关系,屏蔽无用文件
图片添加hash,方便线上CDN缓存
模块导入导出
按需加载,有完备的代码分割解决方案

1.2 Webpack简单介绍

Webpack是用Nodejs语法写的,就是CommonJS写的

Webpack 4比3多了mode属性,可以设置developmentproduction
development特性

  • 浏览器调试
  • 注释、开发阶段的详细错误日志和提示
  • 快速和优化的增量构建机制

production特性

  • 开启所有的代码优化
  • 更小的bundle大小
  • 去除掉只在开发阶段运行的代码
  • Scope hoisting (作用域提升,将多个bundle放到一个闭包里面,可以加快整个代码的运行速度) 和 Tree-shaking (打包的结构只包含实际用到的 exports,将无用代码丢弃,减小bundle大小)

去除掉开发阶段运行的代码,比如console
安装插件:npm install babel-plugin-transform-remove-console --save-dev
然后在项目的babel.config.jsplugin中添加节点。再build就不会有console警告了。
plugins:['transform-remove-console']
这样引入插件后生产环境和开发环境都会去除console,如果只想在生产环境去除console,可以对环境进行判断后引入,优化如下:

if (process.env.NODE_ENV === 'production') {
    proPlugins.push('transform-remove-console');
}
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins:[
    ...proPlugins
  ]
}

Npm和Yarn都是包管理器

mkdir 目录 可以创建目录
cd 目录 进入目录

创建package.json文件

npm init

安装http-server可以启服务,一般项目中不用,只是了解
启服务命令:http-server test,test为目录

1.3 webpack命令

安装webpack: npm install webpack-cli -g
webpack安装之后具有webpack命令
将文件打包导出方式:

// webpack 导出文件 output 输入目录以及文件名 –mode mode类型
webpack src/test.js --output test/test.js –mode none

mode不设置会压缩文件,相当于production行为;设置为none就不会压缩,相当于development行为。

webpack4新特性中可以不使用配置文件:

webpack --mode development 可以直接进行项目打包,默认打包src中的index.js到dist中的main.js

2. 打包配置以及webpack-dev-server

2.1 配置文件打包模块概述

Webpack配置文件就是webpack.config.js
引入:

var webpack = require('webpack');
var path = require('path');
var DIST_PATH = path.resolve(__dirname,'../dist');

配置文件内部结构:

module.exports = {
      // 入口js文件	
      entry: path.resolve(__dirname,'../src/index.js'),
      // 编译输出的路径
      output:{
	path: DIST_PATH,
	filename:'index.js',
      }
      // 模块解析—预处理ts/less等
      module:{}
      // 插件
      plugins:[]
      // 开发服务器
      devServer:{},
      // 指定打包模式,开发模式还是生产模式,指定后就不用在打包命令中再指定了
      mode:development
}

根据配置文件打包命令:

// webpack.config.js中配置了mode,此处就不需要配置了
webpack --config build/webpack.config.js –mode development

打包命令简化:
可在package.json文件中scripts模块中配置

'scripts': {
      'build': 'webpack --config build/webpack.config.js –mode production'
}

配置完之后就可以直接通过npm run build直接打包了

2.2 webpack-dev-server 用于配置开发服务器

安装:npm install webpack-dev-server -D
配置文件 webpack.config.js 中的 devServer 中配置该服务:

hot:true,//热更新
contentBase: DIST_PATH, //热启动文件的文件路径
port:8080, //服务端口
host:'0.0.0.0',//表示可以再服务器外部或者localhost或者IP地址都可以访问
historyApiFallback:true,//项目中的404响应都会替换为index.html
open:true, // 服务启动完成之后自动打开浏览器
useLocalIp:true, // 自动打开浏览器的时候使用自己的IP
proxy:{ // 代理:处理跨域访问接口问题
      '/api':'http://localhost:3000' //表示接口中有api的时候就会代理到http://localhost:3000
},
https:true, // 如果需要https访问接口的话,需要进行该配置

简化启服务的命令如同上面打包一样,需要到package.json文件的scripts模块中配置

'scripts': {
      'dev': 'webpack-dev-server --config build/webpack.config.js –mode production'
}

表示启服务的时候使用webpack.config.js中的配置,使用上面打包的相同配置
命令简化为npm run dev

此时服务启动之后就可以通过http://localhost:8080/index.js访问了,但是dist的文件下面没有index.js文件却还能访问,原因在于启服务打包的文件都在内存中。为什么内存文件在dist目录下面,因为contentBase配置的就是这个目录。此时如果文件有更新就会立刻反应到我们访问的内存服务页面中,原因在于我们配置了hot

3.开发环境和生产环境配置

由于生产环境和开发环境的配置是有差异的,使用同一个配置文件会有一些不方便,所以将webpack.config.js分离成三个js配置文件使用

3.1安装webpack-merge

安装: npm install webpack-merge -D
webpack-merge是一个方法,可以传入多个参数,会将多个参数合并成一个对象,如果有重复的属性名,后面的会覆盖前面的

3.2分离文件

// config目录下面添加三个文件
webpack.base.js // 公共配置
webpack.dev.js // 开发环境的配置
webpack.pro.js // 生产环境的配置

webpack.base.js内容:

module.exports = {
      // 入口js文件	
      entry: path.resolve(__dirname,'./src/main.js'),
      // 编译输出的路径
      output:{
	path: path.json(__dirname,'../dist'),
	filename:'index.js',
      }
      // 模块解析—预处理ts/less等
      module:{}
      // 插件
      plugins:[]
}

webpack.pro.js内容:

const base = require('./webpacl.base.js')
const merge = require('webpack-merge')
module.exports = merge(base,{
      mode:'production',
})

webpack.dev.js内容:

const base = require('./webpacl.base.js')
const merge = require('webpack-merge')
module.exports = merge(base,{
      mode:'development',
      devServe: {
            port: 8080, // 配置端口号:8080
            open: true // 自动打开浏览器
      }
})

3.3配置package.json

'scripts': {
      'build': 'webpack --config config/webpack.pro.js'
      'dev': 'webpack-dev-server --config config/webpack.dev.js'
}

4.多入口文件打包配置

4.1文件打包的入口方式

方式1:打包单个文件,打包结果是单个文件

entry: path.resolve(__dirname,'../src/index.js')

方式2:数组,打包出来会合并成单个文件
如果文件打包需要打包index.jstest.js两个文件,入口文件配置项entry写法可以改成

var SRC_PATH = path.resolve(__dirname,'../src');
entry:[SRC_PATH +'/index.js',SRC_PATH +'/test.js']

方式3:对象,打包结果是多个文件,文件名就是entry中对象的键名

entry:{
      index:SRC_PATH +'/index.js',
      test:SRC_PATH +'/test.js'
}
output:{
      path: DIST_PATH,
      filename:'js/[name].js',
}

4.2文件打包hash配置

由于线上会做cdn缓存,一旦功能或者其他文件有修改,打包更新到线上后,很可能修改不会产生作用,所以我们要对文件进行hash处理
方式1:hash全局更新,一旦某一个文件有更新,所有文件都一起重新生成更新,每次生成的所有文件hash部分名字都一样,cdn缓存就等于失效了

output:{
      path: DIST_PATH,
      filename:'[name].[hash].js',
}

方式2:chunkhash局部更新,只更新修改的文件,并且文件的hash部分是全局唯一的,起到cdn的缓存作用

output:{
      path: DIST_PATH,
      filename:'[name].[chunkhash].js',
}
// chunkhash默认20位hash值打包,如果想配置成5位hash值文件
output:{
      path: DIST_PATH,
      filename:'[name].[chunkhash:5].js',
}

方式3:contenthash,从js里面抽出css文件

4.3glob插件实现动态配置

如果入口文件太多,配置项比较麻烦,可以通过glob插件完成

var glob = require('glob');
var SRC_PATH = path.resolve(__dirname,'../src');
var entryFiles = {};
// 通过glob的sync方法找到所有的同步文件,他的参数可以是正则表达式,返回所有找到的文件路径
var files = glob.sync(path.join(SRC_PATH,'/**/*.js'));
files.foreach(function(file,index){
      var subkey = file.match(/src\/(\S*)\.js/)[1];
      entryFiles[subkey] = file;
})
entry:entryFiles,

4.4提取公共模块配置

当多入口文件输出多个文件时,都引入了JQuery,那两个输出文件都包含JQuery引入,没必要且负面影响很多,可以通过optimization.splitChunks插件(webpack4之前单独插件,之后webpack内置了)的chunks属性设置为all来优化,这样公共部分的JQuery就会被提取出来单独作为一个js被引用
公共模块大小必须大于30kb才会被独立打包,打包出来的文件名是可以设置的

module.exports = {
  // 与entry、output并列
  // 优化打包配置的集合
  optimization: {
    splitChunks: {
      // 提取所有文件的共同模块
      chunks: 'all'
    }
  }
};

5.webpack编译html文件

5.1引入插件html-webpack-plugin打包html文件

安装:npm install html-webpack-plugin -D

// 引入插件
var htmlWebpackPlugin = require('html-webpack-plugin');
// plugins中配置插件
plugins:[
      new htmlWebpackPlugin({
            filename:DIST_PATH+'/index.html',// 文件打包到哪里
            title: '我的第一个测试',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
            template:SRC_PATH+'/pages/index.html',// 模板,也就是原文件路径
            inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
            hash:true,// 会给页面上引入的js文件加上hash值
            minfy:true,// 是否对打包的文件进行压缩
            chunks:['index','common'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
      })
]

5.2多入口html文件打包

方式1:添加多个htmlWebpackPlugin对象

plugins:[
      new htmlWebpackPlugin({
            filename:DIST_PATH+'/index.html',// 文件打包到哪里
            title: '我的第一个测试1',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
            template:SRC_PATH+'/pages/index.html',// 模板,也就是原文件路径
            inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
            hash:true,// 会给页面上引入的js文件加上hash值
            minfy:true,// 是否对打包的文件进行压缩
            chunks:['index','common'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
      }),
      new htmlWebpackPlugin({
            filename:DIST_PATH+'/test.html',// 文件打包到哪里
            title: '我的第一个测试2',// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
            template:SRC_PATH+'/pages/test.html',// 模板,也就是原文件路径
            inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
            hash:true,// 会给页面上引入的js文件加上hash值
            minfy:true,// 是否对打包的文件进行压缩
            chunks:['test'],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
      })
]

方式2:利用glob循环添加多文件打包的html

var glob = reuqire('glob');
var htmlWebpackPlugin = require('html-webpack-plugin');
var DIST_PATH = path.resolve(__dirname,'../dist');
var SRC_PATH = path.resolve(__dirname,'../src');
var pluginAll = [];// 放所有的插件
// 通过glob的sync方法找到所有的同步文件,他的参数可以是正则表达式,返回所有找到的文件路径
var pages = glob.sync(path.join(SRC_PATH,'/pages/**/*.html'));
pages.foreach(function(page,index){
      var pagename= page.match(/src\/pages\/(\S*)\.html/)[1];
      var plug = new htmlWebpackPlugin({
            filename:DIST_PATH+'/'+pagename+'.html',// 文件打包到哪里
            title: '我的第一个测试'+index,// 打包文件的title是可以通过这个参数传递的,通过<head><%=htmlWebpackPlugin.options.title %></head>读取
            template:SRC_PATH+'/pages/'+pagename+'.html',// 模板,也就是原文件路径
            inject:true,// true和body表示将生成的js文件插入到body的底部,head表示插入到head的底部,false表示不插入生成的js文件,默认true
            hash:true,// 会给页面上引入的js文件加上hash值
            minfy:true,// 是否对打包的文件进行压缩
            chunks:[pagename],// 按需引入js文件,不存在的js文件会自动过滤不引入,默认将所有生成的js文件都引入到html内
      })
      pluginAll.push(plug);
})
plugins: pluginAll,
posted @ 2020-11-20 10:34  木-鱼  阅读(202)  评论(0)    收藏  举报