从0快速掌握webpack

202 阅读6分钟

一.创建项目

废话不多说,直接开始初始化一个weboack的项目

yarn init -y
yarn add webpack webpack-cli --dev

项目目录:

image.png

二.测试

新建一些文件夹和文件按,随便写点东西

// src/index.js
console.log("webpack");

// index.html
 <h1>Hello, world!</h1>
 <script src="./src/index.js"></script>

live server 打开 html:

image.png

三.利用 webpack 打包

npx 可以让我们直接运行node_modules下库的自带命令行,而不用写 node_modules下的相对路径

npx webpack

打包完成后,可以看到项目中多了一个 dist 目录:

image.png

四.写点内容

接下来,首先修改一下 index.html 文件, 方便后面使用打包后使用的js文件

<h1>Hello, world!</h1>
<script src="./dist/main.js"></script>

src/data.js

export function getBlogPosts() {
    return ['博客1', '博客2', '博客3']
}

修改index.js 内容,添加打印 博客数据的代码

import { getBlogPosts } from './data';

console.log(getBlogPosts());

完事后,执行npx webpack,可以看到,打包后的js文件内容

(()=>{"use strict";console.log(["博客1","博客2","博客3"])})();

很明显简化了console的内容,还对代码进行了压缩,说明webpack,智能的判断了代码的逻辑。

在回到浏览器,查看

image.png

控制台打印了三个博客列表的数据

五.webpack配置文件

webpack 最核心的就是它的配置文件啦~,文档都有写的很详细,可以修改入口文件配置出口、通过 loader 加载不同的文件,在通过 plugins,在打包过程提供一些代码优化或者是其他的操作,现在我们来测试一下,看看把打包后的文件名修改一下:

新建 webpack.config.js

const path = require('path');

module.exports = {
    mode: "development", // 模式 开发/生产
    entry: "./src/index.js", // 入口
    output: {  // 出口
        filename: "dist.js", // 打包文件
        path: path.resolve(__dirname, "dist"), // 打包文件路径
    },
};

执行 npx webpack,dist目录下就多了一个dist.js 文件,打开可以看到

image.png 接下来,修改 index.html

<script src="./dist/dist.js"></script>

那么之前的 main.js ,就不需要了,我们删除就好了。

六.使用loader来加载css文件,图片文件以及静态资源

修改index.js,根据获取出来的博客列表的数据,来生成一组ul>li元素展示

import { getBlogPosts } from './data';

const blogs = getBlogPosts();
const ul = document.createElement('ul');
blogs.forEach((blog) => {
    const li = document.createElement('li');
    li.innerText = blog;
    ul.appendChild(li);
})
document.body.appendChild(ul);

执行 npx webpack,回到页面:

image.png

新建 src/style.css,写一点简单css代码调整一下:

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: sans-serif;
    list-style: none;
}

body {
    display: grid;
    place-items: center;
}

li {
    padding: 12px;

}

img {
    max-width: 500px;
}

回到 src/index.js,导入刚写的css文件

...
import "./style.css";

..

我们先不使用 loader,执行 npx webpack来打包看看

image.png

这里直接报错了,意思是我们需要一个合适的 loader 来处理这个文件类型,当前,没有配置加载程序来处理此文件。

那么,加载 css 文件,那么我们需要安装两个 loader

yarn add --dev style-loader css-loader

image.png

安装完成后,我们需要在 webpack.config.js 去配置一下:

const path = require('path');

module.exports = {
    ...
    
    // 
    module: {
        rules: [{
            test: /\.css$/i,
            use: ["style-loader", "css-loader"],
        }]
    }
};

执行 npx webpack,看到控制台输出 successfully,回到页面

image.png

可以看到,css样式就应用上了。

那么如何,加载图片呢,对于图片和一些静态资源,webpack 原生支持,就不需要额外安装对应的 loader 了,直接在 webpack.config.js 配置一下:

...
 module: {
        rules: [{
            test: /\.css$/i,
            use: ["style-loader", "css-loader"],
        },{
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
            type: "asset/resource",
        }
        ]
    }
 };

回到 index.js,把图片导入,写点js代码把图片添加到页面上:

...

import CoderImage from "./assets/images/coder.jpg";

...

const image = document.createElement('img');
image.src = CoderImage;
document.body.prepend(image);

执行 npx webpack, 回到页面查看,图片就显示到页面上啦。

image.png

七.使用 html-webpack-plugin

安装 html-webpack-plugin

yarn add html-webpack-plugin --dev

安装好后,来到 webpack.config.js,添加一下配置

...
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    ...
    plugins: [new HtmlWebpackPlugin()],
};

执行 npx webpack,可以看到 dist目录下生成了一个 index.html 文件:

image.png

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
  <meta name="viewport" content="width=device-width, initial-scale=1"><script defer src="dist.js"></script></head>
  <body>
  </body>
</html>

打开到浏览器上看一看,可以看到效果是一样的

image.png

可以看到这个 html 的标题是默认的

image.png

回到 webpack.config.js,

  plugins: [new HtmlWebpackPlugin({
        title: "博客列表",
    })],

执行npx webpack,可以看到就修改掉了

image.png

八.使用 babel-loader

如果是低版本的浏览器,那么就不得不得做兼容,比如,es6的代码就得转成 es5 等等.

安装 babel-loader 相关依赖

 yarn add --dev babel-loader @babel/core  @babel/preset-env

回到 webpack.config.js,

... 
module.exports = {
    mode: "development",
    // 方便看打包后的代码
    devtool: "inline-source-map",
    ...
    module: {
        rules: [
        ...
        {
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: "babel-loader",
                options: {
                    presets: ["@babel/preset-env"],
                },
            }
        }
        ]
    },
};
写好以上配置后,执行`npx webpack`打包命令,可以看到把我们之前写的 `ES6` 的语法转成了 `ES5`匿名函数的形式,说明`babel-loader`就生效了。

image.png

九.使用 terser-webpack-plugin

一个很常见的应用场景,我们在开发完项目后,需要打包项目,压缩代码,减少后的文件体积。

安装 terser-webpack-plugin

yarn add --dev  terser-webpack-plugin

回到 webpack.config.js,

...
const TerserWebpackPlugin = require('terser-webpack-plugin'); 

...
 // 优化
    optimization: {
        minimize: true, // 是否要压缩
        minimizer: [new TerserWebpackPlugin()], // 使用什么缩工具
    },

执行npx webpack打包命令, 查看 dist/dist.js

image.png

代码被压缩了,之前的空格也没有了,后面还有很长的一段加密字符。

十.使用 webpack-dev-server

现在,我们需要在开发的时候,每次要改动的js之后都要重新打包,这样会比较繁琐,webpack 提供了 webpack-dev-server 开发服务器,它可以在启动之后,如果我们修改的是js代码,它就重新打包并刷新页面,现在我们来看一看吧~

安装

yarn add --dev webpack-dev-server
...

... 
devServer: {
    static: "./dist",
},
...

然后来到 package.json,来配置一个启动命令:

...
"scripts": {
    "start": "webpack serve --open"
},
...

然后在 Terminal 里面输入

yarn start 

这样 webpack 就会启动 webpack-dev-server,自动打开页面展示和之前的效果。

image.png

现在,我们随便在index.js新增点内容,再来看看效果

...
const h1 = document.createElement('h1');
h1.innerText = "博客列表";
document.body.prepend(h1);

可以看到h1标签就添加进来了

image.png

现在我们打包后的文件,这个 dist.js 的文件名每次都是一样的,但是浏览器会根据文件名进行缓存,一般我们为了避免浏览器会缓存,我们会给文件名添加一串随机的字符,每次更新之后都改为新的字符,那么webpack也支持自动在打包后生成新的一串字符。

我们来看一看怎么来实现。

回到 webpack.config.js,修改一下配置:

output: {
     // filename: "dist.js",
     filename: "[name].[contenthash].js", 
}

然后终止服务器运行,在运行 npx webpack打包,可以看到生成的文件后就带有生成随机的字符串的文件名

image.png

我们再来index.js, 随便注释一段代码:

// const h1 = document.createElement('h1');
// h1.innerText = "博客列表";
// document.body.prepend(h1);

再来打包观察:

image.png

这里也生成了新的随机字符串的文件,我们删除这四个文件,把上面注释的代码解开,在回到 webpack.config.js 文件,修改回去。

十一.配置别名

接下来,我们来设置设置一下别名,有时候我们在开发的过程中,文件嵌套的可能会比较深,要引入其他目录下的 js 文件,需要使用很多../../../ ....来访问这个文件的路径,webpack 可以让我们指定一个文件别名,来把这一串相对路径,替换掉,这样就可以少些一些字符串.

webpack.config.js,添加一下配置:

resolves: {
    alaias: {
        'xxx', path.resolve(__dirname, "src/xxx"),
    }
}

十二.使用 bundle-analyzer

有时候,我们可能需要打包后分析打包后的结果,哪个文件占的体积比较大,需要下一步的优化。webpack 也有一个可视化的打包分析工具,叫做 webpacl-bundle-analyzer

安装

yarn add --dev webpack-bundle-analyzer

webpack.config.js,添加一下配置:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

...
 
// 插件 
plugins: [
    ...
    new BundleAnalyzerPlugin(),
 ],

执行 npx webpack,打包命令,就会自动打开到浏览器可视化展示:

image.png

可以看到 index.js 是体积最大的,这样就很直观分析了。

十三.总结

webpack 是很多构建工具的基础,它的出现改变了传统前端项目的开发方式,形成了工程化。

webpack 是什么,为什么要用 Webpack,webpack 的 loader 和 plugins 的使用方法等。

webpack 的知识太多了,本文只列举了常用的 loader 和 plugins,道路且长~

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 用于创建 HTML 页面并自动引入 JS 和 CSS
const TerserWebpackPlugin = require('terser-webpack-plugin'); // 压缩打包后的文件
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; //分析打包后体积较大的可视化插件

module.exports = {
    mode: "development",  // 模式 development, production 或 none
    devtool: "inline-source-map",   // 方便看打包后的代码
    entry: "./src/index.js",  // 入口
    output: { // 出口
        filename: "dist.js", // 打包文件 
        // filename: "[name].[contenthash].js", // 生成带有随机字符的文件
        path: path.resolve(__dirname, "dist"), // 打包文件路径
    },
    // 解析
    resolve: {
        alias: {
            // utils: path.resolve(__dirname, "src/utils"),
        }
    },
    // 优化
    optimization: {
        minimize: true, // 是否要压缩
        minimizer: [new TerserWebpackPlugin()], // 使用什么缩工具
    },
    devServer: {
        static: "./dist",
    },
    // 插件 
    plugins: [new HtmlWebpackPlugin({
        title: "博客列表",
    }),
    new BundleAnalyzerPlugin(),
    ],
    // 模块
    module: {
        rules: [{ // 匹配规则
            test: /\.css$/i,
            use: ["style-loader", "css-loader"], // 使用工具
        },
        {
            test: /\.(png|svg|jpg|jpeg|gif)$/i,
            type: "asset/resource", // webpack 自带静态资源打包类型
        },
        {
            test: /\.js$/,
            exclude: /node_modules/, // 排除 不进行打包
            use: {
                loader: "babel-loader",
                options: {
                    presets: ["@babel/preset-env"],
                },
            }
        }
        ]
    },
};

十四.参考

webpack中文文档:webpack.docschina.org/