跳至主要內容

webpack模块打包

白日梦想家yy...大约 14 分钟

webpack模块打包

什么是打包工具

  • 打包并优化项目文件,节省开发效率

额外知识拓展

  • JS文件包含另一个文件使用require方法 require('另一个文件的路径')

  • JS文件如需在index.js入口文件处引入,需要在当前JS页面内暴露

module.exports = {  
    //具体语法
}
  • 插件使用时需要在webpack.config.js顶部引入
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
//声明变量MiniCssExtractPlugin为require引入的mini-css-extract-plugin插件
  • 并在plugin处new对应的插件名
new MiniCssExtractPlugin(options:{  
    template:'',  
    filename: '
'})

webpack基本概念

  • 安装时需要安装webpack和其脚手架webpack-cli
  • 没配置完一项,需要终端输入webpack来执行相关命令
  • webpack原理概念图
Cn3VixstbHclSBz.jpg
Cn3VixstbHclSBz.jpg

1. 树结构:

  • 在一个入口文件中引入所有资源,形成所有依赖关系树状图

2. 模块:

  • 模块就是多个文件打包成一个模块,可以是ES6模块,commonJS模块等,对于webpack来说,就是(css,img,.....)

**3. chunk:

  • 打包过程中被操作的模块文件叫做chunk,例如异步加载一个模块就是一个chunk

**4. bundel:

  • 是最后打包后的文件,可以和chunk长的一样,但是大部分情况下他是多个chunk的集合
  • 为了优化最后生产出的bundle数量可能不等于chunk的数量
  • 因为有可能多个chunk被组合到了一个bundel中

webpack报错

  • webpack安装好后,运行webpack -v会提示错误,或者打包时提示错误
  • 解决方法:
    • 以管理员身份运行IDE
    • 执行:get-ExecutionPolicy,显示Restricted,表示状态是禁止
    • 执行:set-ExecutionPolicy RemoteSigned
    • 这时再执行get-ExecutionPolicy,就显示RemoteSigned

webpack核心概念

  • 打包时必须要暴露文件,里面语法为json格式(键,值模式)
  • 五个核心配置项必要包含在暴露语法内
module.exports = {  
    //具体语法
}
  • 项目目录下新建一个JS(webpack.config.js)文件
  • 建议采用官方默认的名称,如不用,则每次都需要指定,很繁琐

1. 入口

  • entry,入口指示webpack以哪个文件作为入口起点开始打包,分布并构建依赖图
entry: "入口文件具体路径",

2. 输出

  • output,输出指示webpack打包后的资源(bundles)输出到哪里,以及如何命名
  • 语法格式为json格式,filename为输出的文件名称,path为输出文件的具体路径
  • path指定路径时需要调用node.js的包,具体语法如下:

2-1. webpack.config.js文件顶部接收resolve函数

const {resolve} = require('path');

2-2. 在output的path处调用resolve方法

output: {  
    filename: "输出文件的名称",  
    path: resolve(__dirname, '路径目录的名称')
    //调用nodejs的resolve方法来指定输出目录
},

3. 翻译

  • loader(翻译)默认情况下,webpack只能处理js,json格式的文件,
  • 使用loader可以让webpack处理非js,json文件
  • 使用module方法
  • 示例:
module: {   
    rules: [    
            {        //具体语法
                test: /\.css$/,    //正则匹配文件类型
                use:['style-loader','css-loader']    //多个loader
            }  
        ]
},

4. 插件

  • plugins(插件)可以用于执行范围更广的任务,包括打包优化,压缩,重新定义环境等,语法格式为数组模式
plugins: [  
    new HtmlWebpackPlugin()
]

5. 模式

  • mode(模式)指示webpack使用相应依赖模式的配置
  • 指示相应依赖模式时,会自动启用一些对应的插件
  • 开发依赖模式插件较少,生产模式较多
mode:'development'

webpack多入口与多出口

1. 字符串模式,单入口

  • 入口文件需要与要打包的文件形成关联,才可打包
  • 如果只有一个入口,使用字符串,指定一个入口文件,打包一个chunk,chunk的名称是默认的(出口指定的名称)

2. 数组模式,多入口

  • 写多个入口文件,所有的入口文件形成一个chunk,名称是默认的,输出也是一个bundle
entry: ["具体入口路径1","具体入口路径2"],

3. 对象模式,多入口

  • 写多个入口文件,有几个入口文件就会生成几个chunk,并输出几个bundle,chunk的名称是对象的key(键)如下示例1语法
  • 需要在output(输出)filename下更改为以下示例2语法
  • 示例1:
entry: {  
    one:'./具体入口路径',  //左边为key(键)
    two:'./具体入口路径'
},
  • 示例2
output: {  
    filename: "[name].js",  //
    path: resolve(__dirname,'build')
},

4. 特殊用法,对象和数组混合

entry: {  
    //数组多入口
    onea:["具体入口路径1","具体入口路径2"],  
    //单入口
    twob:"具体入口路径3"
},

打包html资源

  • 需要单独使用插件(plugins)对html文件进行处理
  • npm安装html-webpack-plugin插件
  • -D为生产依赖的缩写
npm i html-webpack-plugin -D
  • 需要通过webpack.config.js文件里在顶部添加使用require方法
  • 示例1:
const HtmlWebpackPlugin = require("html-webpack-plugin");
  • webpack.config.js里plugins使用构造方法来引用此插件
  • 默认情况下,会创建一个空的html,目的就是自动引入打包的资源(js/css)
  • 示例2:
plugins: [  
    new HtmlWebpackPlugin()//构造方法
]
  • 如果需要自己指定打包的html,生成自己指定的文件名
  • 则需要在构造方法中加json对象的参数options
  • 在options里使用minfy方法还可移除空格和移除注释
  • 移除空格只会删除html格式的空格,不会删除标签内内容的空格
  • minfy为对象形式
  • 示例3:
plugins: [  
    new HtmlWebpackPlugin(options:{  
        template: "指定需要打包的html文件原路径",  
        filename: "指定打包好的文件名称"  
        minify: {  
            collapseWhitespace:true,   //移除空格                             removeComments:true   //移除注释
        }
    })
],

注意:webstorm中,new HtmlWebpackPlugin后手写options属性时会报错,正确做法是在new HtmlWebpackPlugin后面括号内写入花括号会自动生产options属性

打包多个html文件

  • 打包多个html文件时,需要添加多个new HtmlWebpackPlugin
  • 给每个打包的html文件指定引入的build时,需添加chunk属性
  • 如下示例:
//第一个打包的html文件
new HtmlWebpackPlugin( options:{  
    template: "./src/index.html", //需要打包的路径
    filename: "index.html", //指定打包好的文件名称
    chunks: ['index','vendor'],  //指定引入其它文件的build名称
    minify: {   
        collapseWhitespace:true,    //移除空格 
        removeComments:true  //移除注释
        }
}),

//第二个打包的html文件
new HtmlWebpackPlugin(options:{  
    template: "./src/cart.html",  //需要打包的路径
    filename: "cart.html",  //指定打包好的文件名称
    chunks: ['cart','vendor'],  //指定引入其它文件的build名称
    minify: {    
        collapseWhitespace:true,    //移除空格 
        removeComments:true  //移除注释
        }
})

//指定引入其它文件的build(就是入口文件打包输出的文件)
entry: {  //左边为build名称
    vendor: ['./src/js/jquery.js','./src/js/common.js'],                 index:'./src/js/index.js',  
    cart:'./src/js/cart.js'
},

打包CSS资源

  • 需要npm安装css-loader和style-loader
  • css-loader的作用是把css资源打包到js文件中
  • style-loader的作用是把打包好的js文件里的样式放到html里
  • 单个loader可以直接loader属性使用
  • 多个loader则需要使用数组形式,并匹配规则
  • css文件需要先css-loader后syle-loader
  • 规则是从右到左、从上到下
  • 示例:
module: {   
    rules: [    
            {        //具体语法
                test: /\.css$/,    //正则匹配相关文件类型
                use:['style-loader','css-loader']    //多个loader
                loader: "css-loader"  //单个loader
            }  
        ]
},

打包less和sass资源

  • 打包less和sass文件时,都需要保留css-loader和style-loader
  • 语法与打包css资源一致,只是多了less-loader和sass-loader
  • 正则匹配sass文件类型时,需更改为正则匹配scss类型,而不是sass(sass有sass与scss俩种格式)
    • 打包less
      • 需要npm安装less包和less-loader
    • 打包sass
      • 需要npm安装node-sass包和sass-loader

提取css为单独文件

  • style-loader默认会把css样式通过JS写入到html里
  • 编译修改起来有时不太方便,可以使用MiniCssExtractPlugin.loader替换style-loader来提取css为单独文件,不需要引号引起来
  • 不支持打包为多个build
  • 需要npm安装mini-css-extract-plugin插件
  • 示例:
new MiniCssExtractPlugin(options:{  
    template:'',  
    filename: ''
})
use:[MiniCssExtractPlugin.loader,'css-loader'],

处理CSS浏览器兼容性

  • 需要使用postcss处理兼容性
  • 同样适用于css/less/scss格式
  • npm安装post-loader包和postcss-preset-env插件
  • postcss有单独的文件(postcss.config.js)配置插件 1. 和webpack.config.js一样需要暴露出去
  • 示例1:
module.exports = {  
    plugins:[    
        require('postcss-preset-env')()   
    ]
}

2. 在webpack.config.js里loader处添加到最右面

  • 默认执行顺序时,先处理兼容性,然后在执行其他的loader
  • 会自动在postcss.config.js查找postcss-preset-env插件有没有
>use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader"],

3. 指定兼容浏览器条件

  • 在package.json里使用browerslist方法来指定规则
  • browerslist可以选择对象与数组模式
  • 对象模式可以分别指定开发依赖和运行依赖的规则
  • 默认情况下建议使用数组模式,只指定运行依赖的条件
  • 可以指定多条规则,如下示例2:
  • 示例2:
"browerslist": [ 
    "> 0.2%",//小于20%的浏览器都支持 
    "last 2 versions",//最新的2个浏览器版本 
    "not dead",//废弃的浏览器
]

压缩CSS内容

  • 需要npm安装optimize-css-assets-webpack-plugin插件
  • webpack.config.js顶部引入
  • 然后plugins处new引入执行即可,如下示例1:
  • 示例1:
new OptimizeCssAssetsWebpackPlugin()

打包图片资源

CSS里打包图片方法

  • 需要npm安装url-loader包和file-loader包
  • 俩个包互相是依赖关系,可以加载任何文件
  • url-loader可以将图片转为base64字符串,能更快的加载图片
  • 一旦图片过大,就需要使用file-loader加载本地图片
  • base64格式为计算机把图片生成为二进制指令存储在服务器,但不会存储本地
  • hash为计算机生成base64格式图片的名称,默认名很长,可以hash:10来指定具体名称长度,需要用[ ]包起来使用
  • 故url-loader可以设置图片超过多少字节时,使用file-loader加载图片,如下示例
  • 示例:
{
    test:/\.(png|jpg|jpeg|gif)$/,
    loader:'url-loader',
    options{
        publicPath:'样式内添加的路径名称,例如 ./images '
        outputPath:'图片的路径'  // 指定打包好的目录
        limit:'1024 * 8'  //1024个字节*8倍
        以上为指定规则为8kb的图片打包为base64格式
        name:'[name][hash:10].[ext]' 
        //打包后的名称,可以自定义指定规则
        例如:保留原名称+hash名+格式
        esModule:false,  //老版本浏览器则需此属性
     }
}
  • base64格式为计算机把图片生成为二进制指令存储在服务器,但不会存储本地
  • hash为计算机生成base64格式图片的名称,默认名很长,可以hash:10来指定具体名称长度,需要用[ ]包起来使用
  • ext为默认原图片格式,需要用[ ]包起来使用,如需指定格式,则不需要 [ ]
  • 打包图片资源时,16kb以下建议打包成base64格式
  • 老版本浏览器则还需要在options最后一行添加esModele:false属性

Html里打包图片方法

  • 如需HTML里打包图片路径,则需要再加一个loader 使用html-loader包来处理,只需要添加test规则指定.html格式
  • options规则可以直接沿用之前添加的loader里的规则 而不需要在这个loader里重新编写,然后loader处使用html-loader,具体语法如下
  • 示例2:
WkzJ1whIEpVqo9y.jpg
WkzJ1whIEpVqo9y.jpg

打包其它资源

  • 字体图标库......等等

打包字体库

  • 打包其他格式资源时,如格式较多,可使用exclude(排除正则)来匹配,排除已使用,已打包的格式
  • 使用file-loader来打包其他资源
  • options指定规则,和打包图片的options规则,不用加字节规则 如下示例:
  • 示例:
{    
exclude:/\.(js|json|html|css|less|scss|png|gif|ipg|jpeg)$/,    //格式排除正则表达式  
loader:"file-loader",  
options: {    
outputpath: "路径",//  打包好的路径    
publicPath: " 路径",//css里的引用路径   
name:"[name][hash:6].[ext]"//指定名称、hash名称长度、保留原格式  
        }
}

JS/JSON语法配置检查

  • 默认情况下,js/json格式文件不需要单独处理
  • 但是需要通过eslint单独检查一下JS语法配置
  • 需要npm安装eslint、eslint-loader、eslint-config-airbnb-base、eslint-plugin-import缺一不可,互相形成依赖
  • 下载安装好后需要在package.json里配置规则,具体语法如下:
  • 示例:
"eslintConfig": {  
    "extends": "airbnb-base"  //此规则较多使用
}
  • 只检查当前项目写的js,不需要检查第三方JS插件包
  • 只需要排除node_modules目录
  • options里加上fix:true,可以自动检查后修改,程序逻辑除外
  • 示例2:
{  
    test:/\.js$/,  //正则匹配相关格式
    exclude:/node_modules/,    //正则排除第三方JS插件包
    loader:'eslint-loader' 
    //使用此loader,自动调用package.json里eslintConfig规则
    options: {  
        fix:true
        }
}
  • 如需遇到不想被检查并修复的语法,只需要在相关语法前加上以下规则注释,打包时会自动排除,如下示例3
  • 一般console.log较多,因为只在开发时会用
  • 示例3:
// eslint-disable-next-line
console.log("这是入口文件");

配置开发服务器

  • 可以实时编译、实时浏览器预览
  • 需要npm安装webpack-dev-server
  • 安装后需终端输入webpack serve启动
  • webpack5不支持自动编译,自动浏览器刷新,只能通过webpack.config.js里配置target:"web"项
  • 配置target:"web"项后,先退出webpack secer后再次进入
  • 然后浏览器输入localhost:相应的端口号
  • 其他命令:
//此为更改端口开发服务器端口号
webpack serve --port 3003
  • 通常可以直接在webpack.config.js里配置dev-server选项
  • 包括端口号等等。具体语法如下:
  • 示例:
devServer: {  
    port:3001,  //设置端口号为3001  
    compress:true,  //使用GZIP压缩编译  
    open:true //设置自动打开浏览器
    }

开发环境优化 - HMR模块热替换

  • 此功能可有可无,非必须项
  • 在已经配置好开发服务器的默认情况下,每次更改代码webpack会把所有页面都打包刷新一次,如果文件多的情况下,会非常耗时间,这时就需要用到HMR模块热替换
  • 在devServer配置项里加入hot:true开启HMR功能
  • 开启后,修改代码时,只会更新当前修改代码,而不会刷新整个项目
  • CSS样式的HMR功能需配置style-loader后才能使用
  • Html里HMR功能需要在index.js入口文件entry处加载Html文件
  • JS文件默认没有HMR功能,只能处理非入口文件的JS文件
  • JS需要在入口文件index.js里写入判断,
if(module.hot){  
    module.hot.accept('需要HMR功能的JS文件路径'),function (){        //监听如果加载的JS文件发生变化,执行此回调函数        demo(); //具体执行的回调函数 ,回调函数需要在当前JS文件中暴露
    }
    }

运行(生产)环境优化 - 去除无效代码

  • html无需去除无效代码
  • CSS,JS、第三方框架和库同样适用去除无效代码
  • webpack自带的tree-shaking可以去掉实际上没有使用的JS代码来减少包的大小,必须使用ES6模块化,并开启production运行环境
  • 去除无效CSS代码需要npm安装使用purgecss-webpack-plugin插件
  • 除在webpack.json.js中顶部引入插件外,还需要再webpack.json.js中配置path方法,可以和const {resolve} = require("path")合并为 const {resolve,join} = require("path")
  • 并在plugin处new对应的插件名,写入PATHS方法
  • 然后声明PATHS,具体语法如下:
  • 示例:
const {resolve,join} = require('path'); //顶部
//顶部和之前的path合并,不影响,都调用的是一个path

const PurgecssWebpackPlugin = require('purgecss-webpack-plugin');
//引入purgecss-webpack-plugin插件

const PATHS = {src:join(__dirname,"src")}
//声明并调用PATHS方法

new PurgecssPlugin(options:{                                           paths:glob,sync('${PATHS.src}/**/*',{nodir:true})
}),  //写paths方法
  • 看的比较迷,需要重点去了解

总结

  • 如果拿到别人给的项目文件,或者给别人的项目文件
  • 没有node_modules和build的情况下
  • 只需npm install执行即可恢复,会根据package.json里的配置按顺序执行
  • vue-cli脚手架自带webpack相关配置
上次编辑于:
贡献者: mygit