美文网首页
webpack学习心得

webpack学习心得

作者: Rz______ | 来源:发表于2017-07-22 11:53 被阅读141次

    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官方文档

    相关文章

      网友评论

          本文标题:webpack学习心得

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