从零学脚手架(二)---初识webpack

工作目录

接下来创建 /src 目录、 /src/index.js 文件

在使用vue-cli、react-cli时都会具有一个 /src 目录,这是一个 约定的工作目录。

项目中的代码文件都存放此目录下。

当然此目录名称可以随意设置,只不过约定为 /src。

/src/index.js 文件,是一个 entry(入口) 文件。

打包器 作为一个将 开发环境代码 编译 为 可部署环境代码 的桥梁,那么就必须 至少拥有一个 entry(开发环境代码) 和一个 output(可部署环境代码)

/src/index.js 就作为这么一个 entry(入口)文件

🐋 index.js 文件名称也是约定名称。

wbepack简单配置

entry、output

既然 打包器 必须有 entry(入口) 和 output(输出) ,那么就由这两个属性开始。

webpack  中就是使用 entry 和 output 作为两者的属性名称,这两个属性都可以灵活配置。

const path = require('path')

const modules = {

  //  入口文件

  //  字符串形式

  entry:path.join(__dirname, 'src/index.js'),

  //  对象形式

  // entry:{

  //  'index':path.join(__dirname, 'src/index.js')

  // },

  //  输出文件

  //  字符串形式

  // output:path.join(__dirname, 'dist/[name].js')

  //对象形式

  output:{

    //  输出文件的目录地址

    path:path.join(__dirname, 'dist'),

    //  输出文件名称,contenthash代表一种缓存,只有文件更改才会更新hash值,重新打包

    filename: '[name]_[contenthash].js'

  }

}

//  使用node.js的导出,将配置进行导出

module.exports = modules

entry :入口文件。

属性可设置为:String 、 Object 、 Array

属性值为 String :直接设置一个入口文件地址

属性值为 Object :对入口文件进行详细设置和 可以设置多个入口文件

属性值为 Array :设置多个入口文件

🐋 webpack 允许设置多个 entry(入口) 文件,打包编译出多个文件。一般用于 多页面配置

至于多页面开发配置,就不在此赘述,有兴趣的朋友可以去查阅下 参考资料,单页面程序直接设置 String 即可

output:输出文件。

属性可设置为:String 、Object

属性值为 String :直接设置一个输出文件地址

属性值为 Object :输出文件地址和文件名称详细设置

🐋 webpack在设置 output.filename 时,允许使用 [name] 保留 entry 属性设置的文件名称。

entry 为 String 时, [name] 为文件名称

entry 为 Object 时, [name] 为对象的 key

🐋 output 属性中的 [contenthash] ,是 webpack 提供的一种打包缓存的机制。 webpack 会为打包编译生成一个 hash 值。只有更改源文件后才会重新打包编译,生成新的 hash 。 缓存机制一般只会在 生产模式(production) 使用。

webpack还提供了两个属性 [hash]、[chunkhash] 设置缓存,具体区别请参考:webpack中hash、chunkhash、contenthash区别

🐋 :__dirname 属性是 Node.JS 基础库中属性,表示当前文件的绝对路径。等同于path.dirname()。

🐋 webpack.json 文件中使用了 Node.JS 基础库(require('path')) 获取文件绝对地址,更准确的保证文件目录的完整性。当然也可以只使用相对地址,不过不推荐

此时使用yarn build命令就可以执行 webpack 。 最终会在根目录创建 /dist,并在 /dist 目录下生成一个 .js 文件。

文件中就是 /src/index.js 中的内容

以上就是一个最简单的 webpack 配置,只是将 entry(入口) 文件打包编译到 output(输出)。

不过 webpack 本身是一个强大的 JavaScript应用程序

接下来做小测试,在 /src 目录中创建 index2.js ,并在 index.js 中导入

此时再进行yarn build,/dist 目录下会自动再创建一个 .js 文件,这个 .js 文件就是这次打包的输出问题。

从文件中具有 index.js 和 index2.js 内容

🐋🐋 打包后文件会进行压缩,并且代码会多出许多 webpack 构建的代码。

代码压缩是因为 webpack 默认使用的是 生产模式(production)。

如果想要不压缩代码可以在 webpack.json 文件中添加一个 mode:'development' 属性,至于这两个属性意思下一篇再详细讲解。

这就是webpack 的强大功能之一。 webpack 在打包处理文件时,会递归的构建一个 依赖图(dependency graph) ,根据这个 依赖图 将所有使用到的 JS模块 进行打包。

🐋如果在 index.js 将引入 index2.js 的代码注释或者删除,那么 index2.js 文件内容便不会被打包。有兴趣的朋友可以自行测试。

plugins

在前面说过,webpack 只提供了一个 核心引擎。大部分功能使用 插件化 进行管理

webpack 配置项提供了一个 plugins 属性,该属性是一个 Array 类型,用于设置 plugin。

webpack 在执行时会顺序执行 plugins 中的 plugin 。

const modules = {

    plugins:[

    ],

}

//  使用node.js的导出,将配置进行导出

module.exports = modules

🐋🐋 webpack 默认只是一个 JavaScript应用程序 打包器,所以不会处理CSS、Image、TypeScript等 非js模块,

webpack提供了一个 loader 属性处理 非JS模块(将非JS模块转换为JS模块), 而 plugins 则为 webpack 打包时提供其他扩展。两者结合了促成了 webpack的 插件化 ,使 webpack 可以高度扩展。至于两者的分工和不同,之后会慢慢了解。

🐋 webpack 提供了自定义 plugin 的方法,具体编写规则,有兴趣的朋友可以去参考 官网

html-webpack-plugin

众所周知,运行在浏览器根源是 HTML 文件,HTML 作为 JS 文件的承载容器,哪怕将所有业务逻辑都交给 JS(Document类型) 完成,依然需要一个 HTML 容器承载,那么就需要提供一个提供的 HTML 文件的功能

webpack 中 html-webpack-plugin 就是完成这个功能的

🐋🐋 HTML 容器也是一个 非JS模块,那么为什么使用 plugin处理 而不使用loader呢? 我个人的理解为 HTML 的提供是作为一个 JS 容器存在,而并非要转换为 JS模块 处理

🐋 webpack社区中 以 -plugin 为单词为后缀的库,都为 plugin。而以 -loader 单词为后缀的库,都为 loader。 这也是一种约定规则。

yarn add -D html-webpack-plugin@5.2.0

安装之后,需要在webpack文件中进行引用

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

const modules = {

  plugins: [

    new HtmlWebpackPlugin()

  ]

}

//  使用node.js的导出,将配置进行导出

module.exports = modules

此时执行yarn build,/dist 目录便会多出一个 HTML 文件,此 HTML 还引用此次打包的 JS 文件。

在浏览器中也可以运行此 HTML ,开发者控制台中会打印 JS 文件中的 Console 语句。

真实项目中,HTML 容器也要设置很多东西。例如: Title 、 Meta 或者 icon 等。

并且在vue-cli中,会有一个 HTML 模板文件。在此 HTML 文件添加信息,并且以此文件进行作为容器。

这些信息都是由 html-webpack-plugin 构造参数提供的。

plugins: [

    new HtmlWebpackPlugin({

      //  HTML的标题,

      //  template的title优先级大于当前数据

      title:'my-cli',


      //  输出的html文件名称

      filename:'index.html',


      //  本地HTML模板文件地址

      template:path.join(__dirname, 'src/index.html'),


      // 引用JS文件的目录路径

      publicPath:'./',


      //  引用JS文件的位置

      //  true或者body将打包后的js脚本放入body元素下,head则将脚本放到中

      //  默认为true

      inject:'body',


      //  加载js方式,值为defer/blocking

      //  默认为blocking, 如果设置了defer,则在js引用标签上加上此属性,进行异步加载

      scriptLoading:'blocking',


      //  是否进行缓存,默认为true,在开发环境可以设置成false

      cache:false,


      //  添加mate属性

      meta:{}

    })

  ]

title:HTML 的标题,

属性可设置为: String

此属性在设置 template 属性后会失效

filename:输出的 HTML 文件名称,

属性可设置为:String

默认值为: index.html

template:本地 HTML 模板文件地址。

属性可设置为:String

使用HTML模板文件时,会将 HTML 模板文件内容原封不动的 copy。

例如下面 HTML 模板引用了jquery,打包后的 HTML 依然存在jquery。

publicPath: 引用 JS 文件的目录路径。

属性可设置为:String

例如设置路径为 ./ ,那么在 HTML 文件引用 JS 时就会为 <script src="./main_XXXXXX.js"></script>。

此属性提供了更灵活的项目管理,可以将 HTML 文件和 JS 文件打包到不同目录。

inject: 引用编译后 JS 文件的位置。

属性可设置为:Boolean 、 head 、 body

属性值为 false :代表不引用编译后 JS 文件

属性值为 true 和 body :在 body 元素最后引用编译后 JS 文件 。推荐

属性值为 head:在 head 元素中引用编译后 JS 文件,不推荐

默认值为 true

scriptLoading:设置加载 JS 的方法

属性可设置为:blocking、defer

默认值为 blocking

具体 blocking 、defer 差别可参考defer和async的区别

cache:是否缓存 HTML 文件。

属性可设置为:Boolean

默认值为 true

开发环境(development)时可以设置为 false

meta:设置 meta 属性

在此列举了html-webpack-plugin主要部分属性, 更多属性可以在npm中查看

template 属性需要是一个本地的html路径。

clean-webpack-plugin

之前每次打包编译都会在 /dist 目录创建 .js 文件,久而久之, /dist 就会具有好多无用的文件

/dist 目录往往希望它是一个干净的目录,目录内只具有最新一次的打包生成的文件。这样就可以直接以此目录进行发布。

针对这个需求,社区有大佬开发了clean-webpack-plugin。

clean-webpack-plugin 会在每次打包编译时,清空输出目录。

这个求 --- clean-webpack-plugin

yarn add -D clean-webpack-plugin@3.0.0

将此库直接添加到 plugins 属性即可

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

plugins: [

    new CleanWebpackPlugin()

  ]

此时执行yarn build /dist 目录就只剩下本地打包结果。

🐋🐋

clean-webpack-plugin库使用时为:const { CleanWebpackPlugin } =

与html-webpack-plugin库: const HtmlWebpackPlugin = 不同。

这是因为html-webpack-plugin使用了默认导出: export default ,

而clean-webpack-plugin导出的是指定类型: CleanWebpackPlugin

默认导出方式 可以使用任意变量名称进行导入:const H = require('html-webpack-plugin')。

clean-webpack-plugin也可以从构造函数中传参进行自定义设置

new CleanWebpackPlugin({

      // 是否假装删除文件

      //  如果为false则代表真实删除,如果为true,则代表不删除

      dry:false,


      //  是否将删除日志打印到控制台 默认为false

      verbose: true,


      //  允许保留本次打包的文件

      //  true为允许,false为不允许,保留本次打包结果,也就是会删除本次打包的文件

      //  默认为true

      protectWebpackAssets:true,


      //  每次打包之前删除匹配的文件

      cleanOnceBeforeBuildPatterns:["*.html"],

      //  每次打包之后删除匹配的文件

      cleanAfterEveryBuildPatterns:["*.js"],

    })

dry:是否假装删除文件,官方文档的描述是:Simulate the removal of files。

属性可设置为:Boolean

此属性当为 true 时,则不清空 /dist 目录;当为 false 时,会清空 /dist 目录

默认值: false

verbose:是否将删除日志打印到控制台

属性可设置为:Boolean

默认值: false

protectWebpackAssets:是否保留本次打包的文件

属性可设置为:Boolean

属性值为 false 时,本次打包文件也会被清除掉

默认值: true

cleanOnceBeforeBuildPatterns:设置打包之前删除的文件

属性可设置为:Array

此属性类似一个钩子,在打包执行之前,删除此属性匹配到的文件

默认值: ['**/*']

cleanAfterEveryBuildPatterns:设置打包之后删除的文件

属性可设置为:Array

此属性与 cleanOnceBeforeBuildPatterns 类似,触发时机是打包执行完毕后

默认值: []

使用clean-webpack-plugin时其实不需要配置属性,默认就已经足够使用。

🐋🐋 测试 clean-webpack-plugin 时,需要每次都修改 index.js 文件数据,因为 output 设置缓存,如果不修改源文件,不会重新打包

总结

🐋🐋🐋

打包器将开发环境代码 编译 为可部署环境代码的 “编译器”

webpack运行在Node.JS环境中, 所以写的 webpack配置项 其实是Node.JS 。

webpack配置文件需要抛出一个模块,导出模块必须为 Object 或返回 Object 的函数

webpack只提供一个 核心引擎 ,而其它功能使用 插件化 方式管理

webpack是一个 JavaScript应用程序 ,默认只支持 JS模块 的打包,对于 非JS模块 需要使用 loader 转换为 JS模块

打包器不一定非要使用 Node.JS,也可以使用JAVA、.NET等任何一门语言

打包器其实就是 IO 操作,将entry(入口)文件数据读取并经过一系列操作最终写入到output(输出)文件

如果此篇对您有所帮助,在此求一个star。项目地址: OrcasTeam/my-cli

本文参考

webpack官网

webpack中hash、chunkhash、contenthash区别

本文依赖

webpack@5.24.0

webpack-cli@4.5.0

html-webpack-plugin@5.2.0

clean-webpack-plugin@3.0.0

package.json

{

  "name": "my-cli",

  "version": "1.0.0",

  "main": "index.js",

  "author": "mowenjinzhao<yanzhangshuai@126.com>",

  "license": "MIT",

  "devDependencies": {

    "clean-webpack-plugin": "3.0.0",

    "html-webpack-plugin": "5.2.0",

    "webpack": "5.24.0",

    "webpack-cli": "4.5.0"

  },

  "dependencies": {

    "jquery": "3.5.1"

  },

  "scripts": {

    "start": "node",

    "build": "webpack --config webpack.config.js"

  }

}

webpack.config.js

const path = require('path')

const modules = {

  //  入口文件

  //  字符串形式

  entry:path.join(__dirname, 'src/index.js'),

  //  对象形式

  // entry:{

  //  'index':path.join(__dirname, 'src/index.js')

  // },

  //  输出文件

  //  字符串形式

  // output:path.join(__dirname, 'dist/[name].js')

  //对象形式

  output:{

    //  输出文件的目录地址

    path:path.join(__dirname, 'dist'),

    //  输出文件名称,contenthash代表一种缓存,只有文件更改才会更新hash值,重新打包

    filename: '[name]_[contenthash].js'

  },


  plugins: [

    new HtmlWebpackPlugin({

      //  HTML的标题,

        //  template的title优先级大于当前数据

        title: 'my-cli',

        //  输出的html文件名称

        filename: 'index.html',

        //  本地HTML模板文件地址

        template: path.join(config.root, 'src/index.html'),

        // 引用JS文件的目录路径

        publicPath: './',

        //  引用JS文件的位置

        //  true或者body将打包后的js脚本放入body元素下,head则将脚本放到中

        //  默认为true

        inject: 'body',

        //  加载js方式,值为defer/blocking

        //  默认为blocking, 如果设置了defer,则在js引用标签上加上此属性,进行异步加载

        scriptLoading: 'blocking',

        //  是否进行缓存,默认为true,在开发环境可以设置成false

        cache: false,

        //  添加mate属性

        meta: {}

    }),

    new CleanWebpackPlugin({

        // 是否假装删除文件

        //  如果为false则代表真实删除,如果为true,则代表不删除

        dry: false,

        //  是否将删除日志打印到控制台 默认为false

        verbose: true,

        //  允许保留本次打包的文件

        //  true为允许,false为不允许,保留本次打包结果,也就是会删除本次打包的文件

        //  默认为true

        protectWebpackAssets: true,

        //  每次打包之前删除匹配的文件

        cleanOnceBeforeBuildPatterns: ['**/*'],

        //  每次打包之后删除匹配的文件

        cleanAfterEveryBuildPatterns:["*.js"],

    })

  ]

}

//  使用node.js的导出,将配置进行导出

module.exports = modules

亚马逊测评 www.yisuping.cn

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容