webpack学习心得

webpack是一个前端模块化方案,可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器:加载所需的资源)和plugins(插件:对处理过的文件进行整理)对资源进行处理,打包成符合生产环境部署的前端资源

webpack架构(webpack.config)

1.entry: 定义整个编译过程的起点
2.output: 定义整个编译过程的终点
3.module: 定义模块module的处理方式
4.plugin 对编译完成后的内容进行二度加工
5.resolve.alias 定义模块的别名

webpack的核心module

无论你是jsx,tsx,html,css,scss,less,png文件,webpack视为module。并且每个文件module都会经过相同的编译工序 loader==> plugin。
关于以上这点,以如下一个简单的webpack.config文件为例。看下webpack会做什么

module.exports =  {
        watch: true,
        entry: './index.js',
        devtool: 'source-map',
        output: {
            path: path.resolve(process.cwd(),'dist/'),
            filename: '[name].js'
        },
        resolve: {
            alias:{ jquery: 'src/lib/jquery.js', }
        },
        plugins: [
            new webpack.ProvidePlugin({
                $: 'jquery',
                _: 'underscore',
                React: 'react'
            }),
            new WebpackNotifierPlugin()
        ],
        module: {
            loaders: [{
                test: /\.js[x]?$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            },  {
                test: /\.less$/,
                loaders:['style-loader', 'css-loader','less-loader']
            }, {
                test: /\.(png|jpg|gif|woff|woff2|ttf|eot|svg|swf)$/,
                loader: "file-loader?name=[name]_[sha512:hash:base64:7].[ext]"
            }, {
                test: /\.html/,
                loader: "html-loader?" + JSON.stringify({minimize: false })
            } ]
        }
    };

webpack是如何处理如上webpack.config文件解析:

1. 确定webpack编译上下文context

默认情况下就是node启动的工作目录process.cwd()(取当前工作目录(Current Work Directory),这个不同于“脚本所在目录”。如果你是通过命令行调用的,那么就应该是入口脚本的目录;如果是通过其他进程调用的会继承下来。),当然也可以在配置中手动指定context。
webpack在确定webpack.config中entry的路径依赖时,会根据这个context确定每个要编译的文件(assets)的绝对路径。

2. entry和output 确定webpack的编译起点和终点

顾名思义,entry定义webpack编译起点,入口模块。 对应的结果为compolation.assets
output定义webpack编译的终点,导出目录

编写webpack 插件(Compiler 和 Compilation):https://zhuanlan.zhihu.com/p/20929843?refer=jscss

3. module.loaders 和 module.test 确定模块预编译处理方式

以babel为例,当webpack发现模块名称匹配test中的正则/js[x]?的时候。

  • 它会将当前模块作为参数传入babel函数处理,babel([当前模块资源的引用])。
  • 函数执行的结果将会缓存在webpack的compilation对象上,并分配唯一的id 。
  • 以上的这一步,非常非常关键。唯一的id值决定了webpack在最后的编译结果中,是否会存在-重复代码。
  • 而缓存在compilation对象上,则决定了webpack可以在plugin阶段直接拿取模块资源进行二度加工。
4. plugin阶段贯穿于webpack的整个编译流程,一般用来做一些优化操作。

比如webpack.ProvidePlugin,它会在对编译结果再加工的操作过程中进行自定义的变量注入,当模块中碰到比如这个变量的时候,webpack将从缓存的module中取出underscore模块加载进引用的文件(compilation.assets)。
比如WebpackNotifierPlugin,它会在编译结果ready的时通知开发者,output已经就绪。

5. resolve.alias的作用就是对module模块提供别名,并没有什么特殊的。

创建 import 或 require 的别名,来确保模块引入变得更简单。
例如,一些位于 src/ 文件夹下的常用模块:

alias: {
  Utilities: path.resolve(__dirname, 'src/utilities/'),
  Templates: path.resolve(__dirname, 'src/templates/')
}

现在,替换「在导入时使用相对路径」这种方式,就像这样:

import Utility from '../../utilities/utility';

你可以这样使用别名:

import Utility from 'Utilities/utility';

也可以在给定对象的键后的末尾添加 $,以表示精准匹配:

alias: {
  xyz$: path.resolve(__dirname, 'path/to/file.js')
}

这将产生以下结果:

import Test1 from 'xyz'; // 精确匹配,所以 path/to/file.js 被解析和导入
import Test2 from 'xyz/file.js'; // 精确匹配,触发普通解析

【副作用】 webpack编译过程中的电脑卡慢?

  • 在weback经历以上流程的时候,查看你的内存,你会发现,内存飙升!!!
  • 这一般都是loader阶段,对DSL进行AST抽象语法树分析的时候,由于大量应用递归,内存溢出的情况也是非常常见。
  • output目录不是一个渐进的编译目录,只有在最后compilation结果ready的时候,才会写入,造成开发者等待的时候,output目录始终为空。

【webpack编译对象compilation】 webpack将编译结果导出到output是怎么做到的

  • 如上,webpack在plugin结束前,将会在内存中生成一个compilation对象文件模块tree。
  • 这个阶段是webpack的done阶段 : webpack写入output目录的分割点。
  • 这棵树的枝叶节点就是所有的module[由import或者require为标志,并配备唯一moduleId],
  • 这棵树的主枝干就是所有的assets,也就是我们最后需要写入到output.path文件夹里的文件内容。
  • 最后,这个compilation对象也是所有webpackPlugin的处理的时候的arguments。

总结

  • 对于开发者来说,整体而言webpack的编译过程细节比较多,但是大体的框架还是比较直观。
  • 里面涉及到的类似DSL,AST的概念及模块缓存等等,在构建工具中还是比较常见的,配合watch模式,debug模式,对于开发者来说实在是一大利器。
  • 一切文件皆为模块也和react的一切dom都可以变为JS一样,对前端世界带来了新的开发理念。
    本文大部分引用:https://github.com/slashhuang/blog/issues/1
    webpack官方文档
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,080评论 7 35
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,609评论 7 110
  • 在现在的前端开发中,前后端分离、模块化开发、版本控制、文件合并与压缩、mock数据等等一些原本后端的思想开始...
    Charlot阅读 5,386评论 1 32
  • webpack 介绍 webpack 是什么 为什么引入新的打包工具 webpack 核心思想 webpack 安...
    yxsGert阅读 6,325评论 2 71
  • 一、 添加IP 菜单“配置”--“网络资产探测列表” 二、设置资产探测周期 设置资产探测的扫描周期,格式:天数|小...
    是Jonathan阅读 8,041评论 0 3