美文网首页
Webpack5 系列(一):基础篇

Webpack5 系列(一):基础篇

作者: Eric_见嘉 | 来源:发表于2023-05-15 08:10 被阅读0次

    一、前言

    基础篇主要围绕以下几点展开:

    • 为什么会使用 Webpack?
    • Webpack 打包流程
    • Webpack 的本源
    • Webpack 的配置文件
    • 简化 Webpack 打包流程

    1. 简单案例

    在前端开发中,如果一个页面的逻辑非常多,那么我们就有必要做业务逻辑的划分。

    例如,一个网页包含三个部分,分别是:Header、Sidebar、Content,这些全都通过 JavaScript 来编写,并加入到页面中。

    文件结构如下:

    my-webpack-demo-1/
    |- index.html
    |- index.js
    

    index.html

    <body>
      <div id="root"></div>
      
      <script src="./index.js"></script>
    </body>
    

    index.js

    const dom = document.getElementById('root');
    
    // header
    const header = document.createElement('div');
    header.innerText = 'header';
    dom.appendChild(header);
    // sidebar
    const siderBar = document.createElement('div');
    siderBar.innerText = 'siderBar';
    dom.appendChild(siderBar);
    // content
    const content = document.createElement('div');
    content.innerText = 'content';
    dom.appendChild(content);
    

    2. 面向对象

    a) 封装

    在上面的案例中,实际上 Header、Sidebar、Content 各自的业务逻辑如果很多的话,就可以单独封装到一个构造函数(类)中。

    文件结构如下:

    my-webpack-demo-1/
    |- content.js
    |- header.js
    |- index.html
    |- index.js
    |- sidebar.js
    

    header.js:

    function Header(dom) {
      const header = document.createElement('div');
      header.innerText = 'header';
      dom.appendChild(header);
    }
    

    sidebar.js

    function Sidebar(dom) {
      const siderBar = document.createElement('div');
      siderBar.innerText = 'siderBar';
      dom.appendChild(siderBar);
    }
    

    content.js

    function Content(dom) {
      const content = document.createElement('div');
      content.innerText = 'content';
      dom.appendChild(content);
    }
    

    b) 引入

    封装完毕后,引入到 index.html 中,并在 <script src="./index.js"></script> 前导入三个 js 文件。

    index.html

    <body>
      <div id="root"></div>
      
      <script src="./header.js"></script>
      <script src="./sidebar.js"></script>
      <script src="./content.js"></script>
      <script src="./index.js"></script>
    </body>
    

    index.js

    const dom = document.getElementById('root');
    
    // header
    new Header(dom);
    // side-bar
    new Sidebar(dom);
    // content
    new Content(dom);
    

    3. 模块化

    使用面向对象的方式改进了代码,但是出现了新的问题。什么问题呢?

    问题往往发生在 index.html 中引入 js 的先后顺序出现错误。例如,如果先引入 index.js ,之后再引入其他 js 文件,这样顺序不对而导致解析顺序出错,那么必然报错。实际上,我们希望将所有的文件都引入到 index.js 中,然后只引入这个主文件 ( index.js ) 就好。

    所以,我们不妨使用 ES6 的模块语法(Module)。

    于是,我们需要对代码做一个修改:

    • 通过 export 语法导出模块;
    • 通过 import 语法引入模块。

    a) 功能代码编写与导出

    header.js

    function Header(dom) {
      const header = document.createElement('div');
      header.innerText = 'header';
      dom.appendChild(header);
    }
    
    export default Header;
    

    sidebar.js

    function Sidebar(dom) {
      const siderBar = document.createElement('div');
      siderBar.innerText = 'siderBar';
      dom.appendChild(siderBar);
    }
    
    export default Sidebar;
    

    content.js

    function Content(dom) {
      const content = document.createElement('div');
      content.innerText = 'content';
      dom.appendChild(content);
    }
    
    export default Content;
    

    b) 功能代码引入到主文件

    导出后,将所有的功能代码统一在 index.js 中引入:

    // index.js
    // ES Module
    import Header from './components/header.js';
    import Sidebar from './components/sidebar.js';
    import Content from './components/content.js';
    
    const dom = document.getElementById('root');
    
    // header
    new Header(dom);
    // side-bar
    new Sidebar(dom);
    // content
    new Content(dom);
    

    而 index.html 中只引入 index.js:

    <body>
      <div id="root"></div>
      
      <script src="./index.js"></script>
    </body>
    

    然而,浏览器暂不支持模块语法,会报错。

    于是,Webpack 就应运而生了~

    二、初识 Webpack

    1. 介绍

    a) webpack

    Webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.

    https://www.npmjs.com/package/webpack

    • 打包 ES Modules,CommonJS 以及 AMD Modules(甚至是组合)。
    • 可以在运行时对异步加载的单文件或多个块进行打包(减少初始加载时间)。
    • 在编译期间解析依赖项,从而减少运行时大小。
    • 加载器(Loaders) 可以在编译时对文件进行预处理。比如,TypeScript to JavaScript, Handlebars strings to compiled functions, images to Base64, etc.
    • 高度模块化的 插件(Plugin) 系统。(Highly modular plugin system)

    b) webpack-cli

    webpack 官方的 CLI (Command Line Interface) 工具。

    webpack CLI provides a flexible set of commands for developers to increase speed when setting up a custom webpack project. As of webpack v4, webpack is not expecting a configuration file, but often developers want to create a more custom webpack configuration based on their use-cases and needs. webpack CLI addresses these needs by providing a set of tools to improve the setup of custom webpack configuration.

    2. 安装

    mkdir webpack-demo
    cd webpack-demo
    npm init -y
    npm i webpack webpack-cli --save-dev
    

    webpack 和 webpack-cli 是两个不同的包,--save-dev 可以简写为 -D,表示保存并写进开发依赖中。

    注意:webpack-cli 必须安装,否则运行不了 webpack!

    查看版本:

    npx webpack -v
    

    npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装!

    3. 文件结构

    将文件按照如下位置安放:

    webpack/
    |- /src
      |- /components
        |- content.js
        |- header.js
        |- sidebar.js
      |- index.js
    |- index.html
    |- package.json
    

    4. 打包

    执行打包命令:

    npx webpack-cli
    

    运行结果如下:

    打包完成后,就会出现一个 dist 目录,里面有一个 main.js 文件,这就是打包完成的 js 文件。

    或者通过:npx webpack 也可以。

    5. 效果

    在打包结束后,需要修改 index.html 中脚本的引用位置:

    <body>
      <div id="root"></div>
    
      <script src="./dist/main.js"></script>
    </body>
    

    页面效果如下:

    网页正常显示。

    那么,webpack 做了什么事情?它将原来的文件翻译打包成了浏览器看得懂的 js 文件 ( main.js )。

    6. 本源

    在某种程度上,我们可以将 webpack 理解为 js 代码翻译器吗?其实不然!

    它只是可以识别 js 的模块语法而已,例如,上面的 import、export 语法 ( Header、Sidebar、Content 就是模块。),然而对于其他的 js 语法它是不认识的!

    正如它的官方文档所说,Webpack is a module bundler. webpack 是一个模块打包工具!它可以将多个模块打包到一起。另外,对于 CommonJS(Node.js 用)、CMD、AMD 这些模块规范,webpack 也可以识别并打包。

    除了 js 文件以外,webpack 还可以打包其他模块文件,例如, ts 文件,css/sass/less/stylus 文件,图片文件等等。

    阅读参考:

    三、Webpack 配置文件

    在第二部分中,我们通过 npx webpack 的形式进行打包,实际上我们用的是 webpack 默认的配置来打包的。

    那么如何自定义打包配置呢?

    1. 在根目录下创建配置文件 ( 默认是:webpack.coonfig.js )
    2. 编写打包配置项

    注意,此时的文件结构如下:

    webpack/
    |- /src
      |- /components
        |- content.js
        |- header.js
        |- sidebar.js
      |- index.js
    |- index.html
    |- package.json
    

    1. 默认的配置文件

    在文件根目录下创建:

    touch webpack.config.js
    

    webpack.config.js

    // webpack 配置文件
    const path = require('path'); // node.js 的路径模块
    
    module.exports = {
      // entry: './src/index.js', // 入口文件(简写形式)
      entry: {
        main: './src/index.js',
      },
      output: {
        path: path.resolve(__dirname, 'dist'), // 打包后的路径
        filename: 'bundle.js', // 打包后的文件名
      }
    }
    

    以上是简单的打包配置,配置项包括入口文件、打包路径、打包文件名。

    其中,入口文件是指一个项目的主文件,一般来说,所有的模块都会被加入到这个文件中,类似于 vue-cli 中的 main.js 文件。

    之后,运行 npx webpack,即可按照此配置文件进行打包。

    2. 自定义的配置文件

    现在,如果我们并没有将配置文件设置为默认的 webpack.config.js,

    而是使用了其他的名字,例如:my-webpack-config.js,

    在这种情况下,我们该如何以这个自定义的配置文件作为配置的标准来打包呢?

    通过以下命令即可:

    npx webpack --config my-webpack-config.js
    

    运行结果如下:

    3. 简化打包流程

    以上,我们都是通过手动的 npx webpack 来打包的!

    实际上,还可以利用 package.json 中的 scripts 字段来编写运行脚本,通过脚本进行打包。

    // ...
    "scripts": {
      "bundle": "webpack"
    },
    // ...
    

    之后,通过 npm run bundle 就可以打包了。

    疑惑:为什么 "bundle" 后面不写成:"npx webpack" 呢?

    原因在于,当你运行 npm run bundle 时,它会先去 node_modules 文件夹中去找是否安装了 webpack 这个指令,如果有就会执行了,相当于被翻译成了 webpack 这个命令。这个与 npx webpack 是类似的,但并不是相等的,本文前面有叙述过,请自行查找~

    (也就是看 node_modules 中的 webpack 下的 bin 中是否有对应的可执行指令文件,这块需要了解 Node.js 的内容,此篇不论。)

    参考:https://webpack.js.org/guides/getting-started/

    4. 打包模式

    每次打包完,打包内容中总有一段 WARNING 警告,提醒我们设置打包模式(mode)。

    默认情况下,它被设置为 'production',我们也可以自行配置:

    // webpack.config.js
    const path = require('path');
    
    module.exports = {
      mode: 'development', // 'development' | 'production'
      // entry: './src/index.js',
      entry: {
        main: './src/index.js',
      },
      output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
      },
    }
    

    可以配置为开发模式或者生产模式:

    • 开发模式:本地环境
    • 生产模式:线上环境(代码是压缩的)

    具体有何不同,在打包后,打开 dist 文件夹下的 main.js,便可一目了然,此处不再赘述。

    小结

    以上,是本篇的所有内容。
    最后回答一下前言部分的问题:

    • 为什么会使用 Webpack?模块化、预处理。
    • Webpack 打包流程:确保存在 package.json 的情况下去打包,注意配置项的设置。
    • Webpack 的本源:模块打包器,记住是模块。
    • Webpack 的配置文件:webpack.config.js,配置项:mode/entry/output
    • 简化 Webpack 打包流程:设置 package.json 中的 scripts 字段。

    以上,感谢您的阅读~

    相关文章

      网友评论

          本文标题:Webpack5 系列(一):基础篇

          本文链接:https://www.haomeiwen.com/subject/lgjmsdtx.html