Webpack入门

293 阅读6分钟

1.webpack简介

1.1webpack是什么?

webpack是一种前端资源构建工具,一个静态模块打包器(module bundler)。在webpack看来,前端多有的资源文件(js/json/css/img/less/…)都会作为模块处理。它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)

1.2 webpack五个核心概念

  • Entry: 入口(entry)指示webpack以哪个文件为入口起点开始打包,分析构建内部依赖图。

  • Output: 输出指示webpack打包后的资源bundles输出到哪里去,以及如何命名。

  • Loader: Loaderwebpack能够去处理那些非Javascript文件(webpack自身只理解Javascript)。

  • Plugins: 插件可以用于执行范围更广的任务,插件的范围包括,从打包优化压缩,一直到重新定义环境中的变量等。

  • Mode:模式指示webpack使用相应模式的配置。

    选项描述特点
    development:会将 DefinePluginprocess.env.NODE_ENV 的值设置为development,启用 NamedChunksPluginNamedModulesPlugin能让代码本地调试的运行环境
    production:会将 DefinePluginprocess.env.NODE__ENV 的值设置为production。启用 FlagDependencyUsagePluginFlagIncludedChunksPlugin ModuleConcatenationPluginNoEmitOnErrorsPluginOccurrenceOrderPluginSideEffectsFlagPluginTerserPlugin能让代码优化上线的运行环境

2.webpack打包初体验:

目录结构如下:

代码:

// index:webpack的入口起点文件

import data from "./test.json";
import test from "./test.css";
function add(x,y){
    return x + y
}
console.log(add(1,2))
console.log("我是json",data);
//test.json
{
  "key": "测试json文件打包"
}

// test.css
body{
    background-color: #42b983;
    height: 1000px;
    width: 100%;
}

文件夹根目录下的index.html:

  • 这里script引入的是打包后的main.js文件
  • build为根目录下新建的文件夹
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="./src/test.css">
</head>
<body>

<script src="./build/main.js"></script>
</body>
</html>

安装以及打包操作:

安装:
  • 全局下先安装:npm i webpack webpack-cli -g
  • 项目中安装:npm i webpack webpack-cli -D

打包:

  • 开发环境:
    • 命令:webpack ./src/index.js -o ./build --mode=development-o的意思就是output输出)
    • 作用:webpack能够编译打包jsjson文件,并且能够将es6的模块化语法转换成浏览器能识别的语法。
  • 生产环境:
    • 命令:webpack ./src/index.js -o ./build --mode=production
    • 作用:在开发配置功能上多一个功能,压缩代码
问题:

在引入css文件后在打包,发现报错:

结论:
  1. webpack能处理jsjson文件,不能处理css/img等其他资源
  2. 生成环境开发环境ES6模块化编译成浏览器能识别的module
  3. 生产环境开发环境多一个压缩js代码

3.webpack打包资源:

1.对于cssless的打包:

  • 项目的根目录下创建一个webpack.config.js文件,该文件的作用主要是用来告诉webpack---你要去干些啥
  • const {resolve} = require("path");:用来拼接绝对路径用的
    • resolve(__dirname,"build"): __dirname表示的是当前的文件的目录绝对路径,是nodejs的一个变量
  • module中的rules是用来配置loader
    • test用来匹配文件
    • use是来处理匹配文件的,use数组中的执行顺序是从下向上
  • 打包less文件的时候需要注意安装lessless-loaderless不用配置到use数组中
//告诉webpack的都干点啥

// 所有的构建工具都是基于nodejs平台运行的,模块化默认才用commonjs的语法

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

module.exports = {
    // 入口
    entry:"./src/index.js",
    // 出口
    output:{
      //打包输出的文件名字
        filename:"build.js",
        //__dirname表示的是当前的文件的目录绝对路径,是nodejs的一个变量
        path:resolve(__dirname,"build")
    },
    //loader的配置
    module:{
        rules:[
            //详细的loader的配置
            {
                //test -- 匹配以.css文件结尾的
                test:/\.css$/,
                //use的意思是使用那些loader出处理,use数组中的执行顺序是从下到上
                use:[
                    //将style标签以及js中的样式资源插入到head中生效
                    "style-loader",
                    //css-loader是将css文件转化为commonjs模块,加载到js中,里面的内容是样式字符串
                    "css-loader"
                ]
            },
            {
                //test -- 匹配以.css文件结尾的
                test:/\.less$/,
                //use的意思是使用那些loader出处理,use数组中的执行顺序是从下到上
                use:[
                    //将style标签以及js中的样式资源插入到head中生效
                    "style-loader",
                    //css-loader是将css文件转化为commonjs模块,加载到js中,里面的内容是样式字符串
                    "css-loader",
                    "less-loader",
                ]
            }
        ]
    },
    // 插件
    plugins:[
        //插件的详细配置
    ],
    //模式
    mode:"development"
}

2.对于html的打包:

这里使用插件对html进行处理。

npm i html-webpack-plugin -D
webpack.config.js代码:
  • 安装完了 html-webpack-plugin之后,使用时是需要引入
    • const HtmlWebpackPlugin = require("html-webpack-plugin");
  • template:就是一个模板嘛,复制"./src/index.html"文件资源,并自动引入打包输出所有的资源(js/css)
//webpack.config.js
const {resolve} = require("path");
const  HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports={
    entry:"./src/index.js",
    output:{
        filename:"html.js",
        path:resolve(__dirname,"build")
    },
    module:{
        rules:[

        ]
    },
    plugins:[
        // 默认创建一个空的html,自动引入打包输出所有的资源(js/css)
            new HtmlWebpackPlugin({
                //复制"./src/index.html"文件资源,并自动引入打包输出所有的资源(js/css)
                template:"./src/index.html"
            })
    ],
    mode:"development"
}
打包结果:

会发现build文件夹下面多生成了一个index.html文件

3.对于图片资源的打包:

文件夹结构:
├─webpack.config.js
├─src
|  ├─bbb.jpeg
|  ├─index.html
|  ├─index.js
|  └index.less
webpack.config.js:

这里对于入口的index.js以及其他的内容就不做多余阐述了,和上面基本类似。直接来看下关于webpack.config.js的配置:

  • 这里使用url-loader对于图片做处理,但是url-loader依赖于file-loader,所以两个都是需要安装的(只引入一个)
  • options中的limit:如下代码中注释部分
const {resolve} = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports={
    entry:'./src/index.js',
    output:{
        filename:"build.js",
        path:resolve(__dirname,"build")
    },
    module:{
        rules:[
            {
                test:/\.less$/,
                use:[
                    "style-loader",
                    "css-loader",
                    "less-loader",
                ]
            },
            {
                test:/\.(jpg|png|gif|jpeg)$/,
                //使用单个loader的书写形式
                //需要下载两个包,url-loader和file-loader,因为url-loader依赖于file-loader去做事,所以需要下载两个
                loader:"url-loader",
                options:{
                    // 作用:图片大小小于8kb就还会被base64处理
                    // 优点:减少请求数量,减轻服务器压力
                    // 缺点:图片体积会更大(文件请求速度会稍微慢些)
                    limit:8 * 1024
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:"./src/index.html"
        })
    ],
    mode:"development"
}
新问题:

url-loader可以处理css中的图片,但是对于html中的图片,打包后build/index.html文件用浏览器打开后发现图片无法显示...

  • 这个时候需要html-loader
  • url-loaderhtml-loader中的optionsesModule都设置为了false
    • 原因:关闭url-loaderes6module模块化,使用commonjs的模块化
  • name:"[hash:10].[ext]":
  • [hash:10]:取hash值的前10
  • [ext]:取文件的原来的后缀名
const {resolve} = require("path")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports={
    entry:'./src/index.js',
    output:{
        filename:"build.js",
        path:resolve(__dirname,"build")
    },
    module:{
        rules:[
            {
                test:/\.less$/,
                use:[
                    "style-loader",
                    "css-loader",
                    "less-loader",
                ]
            },
            {
                test:/\.(jpg|png|gif|jpeg)$/,
                //使用单个loader的书写形式
                //需要下载两个包,url-loader和file-loader,因为url-loader依赖于file-loader去做事,所以需要下载两个
                loader:"url-loader",
                options:{
                    // 作用:图片大小小于8kb就还会被base64处理
                    // 优点:减少请求数量,减轻服务器压力
                    // 缺点:图片体积会更大(文件请求速度会稍微慢些)
                    limit:8 * 1024,
                    esModule:false,
                    //给图片进行重命名
                    name:"[hash:10].[ext]"
                },

            },
            {
                test:/\.html$/,
                // html-loader 负责引入html中的图片,从而能被url-loader处理
                loader: "html-loader",
                options: {
                    esModule: false
                }
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:"./src/index.html"
        })
    ],
    mode:"development"
}

4.对于其他资源的打包:

目录结构:
src
├─iconfont.css
├─iconfont.eot
├─iconfont.svg
├─iconfont.ttf
├─iconfont.woff
├─iconfont.woff2
├─index.html
└index.js

这里为了测试,使用了iconfont的资源

webpack.config.js
  • 通过rules中对象的exclude:/\.(css|js|html)$/排除这些后缀的文件,剩下的就是其他文件(这里指的是字体文件等)
  • 通过file-loader来处理其他文件的加载
const {resolve} = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry:"./src/index.js",
    output:{
        filename:"build.js",
        path:resolve(__dirname,"build")
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    "style-loader",
                    "css-loader",
                ]
            },
            {
                //使用exclude去排除这些后缀,那么剩下的就是其他资源
                exclude:/\.(css|js|html)$/,
                loader:"file-loader"
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:"./src/index.html"
        })
    ],
    mode:"development"
}

4.webpack-dev-server

修改src中的文件后需要手动编译,webpack-dev-server为其自动化提供了可能

直接上webpack.config.js文件:

  • contentBase:项目构建后的路径
  • compress:是否开启gzip压缩
  • port:端口号
  • open:编译过后自动打开
const {resolve} = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry:"./src/index.js",
    output:{
        filename:"build.js",
        path:resolve(__dirname,"build")
    },
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    "style-loader",
                    "css-loader",
                ]
            },
            {
                //使用exclude去排除这些后缀,那么剩下的就是其他资源
                exclude:/\.(css|js|html)$/,
                loader:"file-loader"
            }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            template:"./src/index.html"
        })
    ],
    mode:"development",
    devServer:{
        //项目构建后的路径
        contentBase:resolve(__dirname,"build"),
        //启动gzip压缩
        compress:true,
        // 端口号
        port:3000,
        // 编译后自动打开浏览器
        open:true
    }
}