zoukankan      html  css  js  c++  java
  • [Webpack]webpack学习之旅(第三天)

    webpack行程

    1. 第一天:webpack安装与基本使用

    2. 第二天:如何处理各种格式的文件

    3. 第三天:如何生成自定义Html文件

    4. 第四天:如何实现开发模式下的配置

    5. 第五天:如何实现第三方插件的引入

    6. 第六天:如何提取公用代码同时减少冗余代码

    7. 第七天:研究vue-cli脚手架源码

    第三天:如何生成自定义Html文件

     webpack学习之旅的第三天,我们稍作调整。前面两天的行程有点太累,今天我们针对前面的构建流程进行一些优化,比如:我们每次创建新项目都需要手动创建一个Html文件同时手动插入script标签并预先引入构建后的JS资源文件。如果我们每次打包创建的bundle名称加入了hash值 ( 为了缓存的目的 ) ,那么我们就需要手动去修改html文件中引入的JS资源文件名,显然这种方式是不科学的。再比如,我们目前遇到的仅仅是单页面应用,如果我们打包的是多页面应用,比如我们有两个页面,分别对应了两个JS文件入口,那么我们的entry就是两个chunk,构建后的bundle也是两个。难不成我们要手动创建两个html文件,然后分别引入不同的JSbundle文件吗?所以这就引出了我们今天要去参观的html-webpack-plugin插件。

    1. clean-webpack-plugin

    在了解html-webpack-plugin之前,我们先来了解 clean-webpack-plugin 插件。这个插件的作用很简单,就是用来清除我们文件目录的工具。如果使用了hash值,那么每次打包构建后的文件都会不一样,手动清除目录是很繁琐的。我们需要工具来提高效率。使用方法也很简单,第一步肯定是要安装这个插件

    npm install clean-webpack-plugin --save-dev
    

    接着我们只需要在webpack.config.js 配置文件的 plugins 选项中添加即可。 凡是插件,需要添加到 plugins 选项中。这个选项接收一个数组,数组中堆满了所有构建需要用到的各种插件。

    const cleanWebpackPlugin = require("clean-webpack-plugin")
    
    module.exports = {
        plugins: [
            new cleanWebpackPlugin([
                "dist"
            ], {
                verbose: false
            })
        ]
    }

    使用方法非常简单,第一个参数paths是文件夹数组,可以指定要删除的目录或者目录下的特定后缀名的文件等等。第二个参数 options 可以指定 root 根目录 ( 默认是 __dirname ) ,也可以指定 verbose ( true表示在终端输出中会显示删除的日志信息 false表示不显示) ,还可以指定 exclude 数组以表示哪些文件需要排除在外。

    2. html-webpack-plugin

    现在正式开始讲解html-webpack-plugin插件的使用。这个插件的目的是帮助我们生成一个包含构建后资源的html文件。那么我们是否需要一个html模板呢? 俗话说是先有鸡还是先有蛋呢?我们想创建一个html文件,那肯定是预先需要一个html壳子的呀,然后插件在这个基础之上帮我们把各种标签如 script meta style title等等信息插入到它应该存放的位置。所以我们就先创建一个最简单的html文件,如下

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
    </body>
    </html>

    只有DOCTYPE head title 和 body,除此之外什么都没有写。接着我们来看插件如何帮助我们生成最终的html文件。

    第一步是安装这个插件

    npm install html-webpack-plugin --save-dev

    接着 webpack.config.js 配置文件中的 plugins配置如下

    const htmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
        entry: {
            app: path.resolve(__dirname, "./src/index.js")
        },
        output: {
            path: path.resolve(__dirname, "./dist"),
            filename: "[name]-[hash:4].js"
        },
        plugins: [
            new htmlWebpackPlugin({
                template: path.resolve(__dirname, "./index.html"),
                filename: "app.html",
                title: "使用html-webpack-plugin插件自动插入打包资源文件来生成html文件",
                chunks: [ "app" ],
                inject: "body",
                favicon: path.resolve(__dirname, "./favicon.ico"),
                meta: {
                    "utf-8": {
                        "charset": "utf-8"
                    },
                    "viewport": "width=device-width, initial-scale=1.0",
                    "X-UA-Compatible": {
                        "http-equiv": "X-UA-Compatible",
                        "content": "ie=edge"
                    }
                },
                minify: false
            })
        ]
    }

    接着简短介绍下options中各个参数的含义

    template: 模板文件,就是前面提到的那个壳子

    filename:  自动生成的html文件名称,可以指定二级目录

    title: html文件中的title标签内容,也就是页面标题,注意,一定要预先在模板中使用 <%= htmlWebpackPlugin.options.title %> 进行占位。

    chunks: 指定哪些chunk打包后的文件才能够放入到html文件中,这里就涉及到我们前面提到的应用场景了,两个页面分别对应不同的chunk

    excludeChunks: 指定哪些chunk被排除在外,不会添加到html文件中。

    inject: 指定页面需要的这些资源文件插入到html文件的哪个部分,比如 true | body 表示插入到 body标签中, head 表示插入到 head标签中, false则表示不要插入,由我开发者来自行插入。

    favicon: 指定页面的 favicon小图标文件

    meta: 指定页面的meta 信息,参考上图即可。针对meta标签格式不是 <meta name="xxx", content="yyy" /> 这种情形的请使用上面的方式进行定义,如 charset=utf-8等等

    minify: 指定页面输出格式,默认可以不设置。当你有html文件输出格式要求时再来设置。具体各个选项可以查看官方文档,给出传送门 html-minifier的git仓库,一般可以设置为如下简单要求:

    {
        minify: {
            collapseWhitespace: true,
            removeComments: true,
            removeRedundantAttributes: true,
            removeScriptTypeAttributes: true,
            removeStyleLinkTypeAttributes: true,
            useShortDoctype: true
        }    
    }
    

    collapseWhitespace 是否把所有的空白符全部去掉

    removeComments 是否把注释去掉

    removeRedundantAttributes 是否将多余的标签特性移除,比如input标签默认type=text,比如 a标签的name和id重复了会移除name  

    removeScriptTypeAttributes 是否移除 script标签type特性 type="text/javascript"

    removeStyleLinkTypeAttributes 是否移除 link style标签的 type特性

    useShortDoctype 是否使用更短的DOCTYPE文档声明

    OK,有了上面这些准备工作,我们在 ./src/index.js 文件中引入CSS样式文件,然后简单添加一句 console.log("hello") 打印语句。通过webpack命令最后构建的日志信息如下

    具体源代码可以查看项目git仓库中的 /day3/demo1

    3. 高级内容

    一般来说,对于普通开发者,了解这个插件到这种程度就可以了,可就是有这么一群人,他们会想,为什么我们要预先提供一个html壳子呢?难道就没有办法让插件给我们自动生成一个html壳子呢?于是我在官网上找到了这么一个插件 html-webpack-template 。天呐,还真有这种工具呢,那我们就一起来快快使用吧。

    第一步依然是需要先安装这个插件

    npm install html-webpack-plugin html-webpack-template --save-dev

    接着就是调整我们的 html-webpack-plugin 的 options 选项了,首先 template 参数指定为 这个插件实例 require("html-webpack-template")

    接着这个插件给我们丰富了 html-webpack-plugin的 options选项,同时也规定了 inject 参数必须为 false 其他常用参数选项可以参考如下代码

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
        plugins: [
            new HtmlWebpackPlugin({
                inject: false,
                template: require("html-webpack-template"),
                title: "使用html-webpack-template生成html文件",
                appMountId: "myApp",
                appMountHtmlSnippet: "<p>我是通过appMountHtmlSnippet插入的内容</p>",
                appMountIds: ["gallery", "panel"],
                bodyHtmlSnippet: "<p>我是插入到body中的p标签</p>",
                lang: "zh-CN",
                window: {
                    "userName": "joy"
                },
                chunks: [ "app" ],
                meta: [
                    {
                        name: "viewport",
                        content: "width=device-width, initial-scale=1.0",
                    }
                ]
            })
        ]
    }

    常用的扩展参数选项讲解

    a. appMountId 表示 会创建这样一个ID的DIV标签,同时将 appMountHtmlSnippet 内容插入其中

    b. appMountHtmlSnippet 表示 插入到 appMountId 的 html片段内容

    c. appMountIds 表示会创建一系列ID的DIV标签

    d. bodyHtmlSnippet 表示会插入到body内部起始位置的 html片段内容

    e. lang 指定 html文件的 语言

    f. window 定义全局作用域下的变量

    g. meta 接收一个数组,默认已经为我们添加了 charset 与 <meta http-equiv="x-ua-compatible" content="ie=edge"> 这两个meta标签。

    其余meta可以通过 {name, content}方式插入

    h. headHtmlSnippet 表示会插入到head 标签内部起始位置的 html片段内容

    通过webpack构建后生成的html文件如下

    <!DOCTYPE html>
    <html lang="zh-CN">
      <head>
        <meta charset="utf-8">
        <meta content="ie=edge" http-equiv="x-ua-compatible">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>使用html-webpack-template生成html文件</title>
        <link href="app.css" rel="stylesheet" />
      </head>
      <body>
        <a href="./a.js">我是插入到body中的a链接</a>
        <div id="myApp">
        <p>我是通过appMountHtmlSnippet插入的内容</p>
        </div>
        <div id="gallery"></div>
        <div id="panel"></div>
        <script type="text/javascript">
          window['userName'] = "joy";
        </script>
        <script src="app-3a6b.js" type="text/javascript"></script>
      </body>
    </html>

    具体源代码可以查看项目git仓库 /day3/demo2

    4. 后记

    第三天,我们只是简化了最终html文件的生成过程,以及通过插件使得我们可以自由定义最终生成的html文件的各种样式。而针对webpack内部对JS资源构建的细节并没有深入介绍。今天介绍的这两个生成html文件的插件可以配合我们第二天介绍的 html-loader 一起使用,比如我们在html模板中引入了一张图片,最后打包时我们会将这张图片的资源引用地址进行修改等等。这部分的源代码及讲解放到后面再说,还是先Mark,因为不是很常用。另外,大家有没有发现我们每次调整源码之后都需要手动再次执行webpack命令,而且最终的 Index.html文件时都是通过file协议打开的,有没有办法实现Http协议打开呢,毕竟我们最终的产品都是通过http协议访问的。大家别急,这就是我们第四天即将前往的景点——webpack-dev-server插件。

  • 相关阅读:
    系统综合实践第三次实践
    系统综合实践第二次实践作业
    第1次实践作业
    软工总结
    团队Beta演示
    团队Beta5
    软工实践个人总结
    第09组 Beta版本演示
    第09组 Beta冲刺(5/5)
    第09组 Beta冲刺(4/5)
  • 原文地址:https://www.cnblogs.com/joyjoe/p/10361724.html
Copyright © 2011-2022 走看看