Giter Club home page Giter Club logo

geektime-webpack-course's Introduction

geektime-webpack-course

《玩转webpack》极客时间课程源码和课件

公众号

扫码关注公众号,定期推送 webpack 及其它前端技术文章,前期推送频率每周一篇 webpack 文章。

geektime-webpack-course's People

Contributors

cpselvis avatar dependabot[bot] avatar gnosis23 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

geektime-webpack-course's Issues

为什么 webpack4 默认支持 ES6 语法的压缩?

在专栏课程里,有位同学提到过一个很有意思的问题:“我没装 babel,js 入口里写了个箭头函数,运行 webpack 构建命令后,也成功编译了。这是为什么?”。今天就带领大家一起去探讨下这个话题。

在使用 webpack 的时候,很常见的一个构建优化手段就是缩小构建目标。比如在构建阶段只构建 src 里面的模块代码,对于 node_modules 里面所引入的三方包不进行构建操作。

发现问题

如果使用的是 webpack 3.x 版本,编写的构建脚本类似这样的,我们通过设置loader 里面的 exclude 字段避免由于解析 node_modules 里面的模块造成的构建耗时:

const path = require('path');
const webpack = require('webpack');

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'happypack/loader',
                exclude: path.join(__dirname, 'node_modules')
            }
        ]
    }
    plugins: [
        new webpack.optimize.UglifyJsPlugin()
    ]
};

我们经常会遇到一个问题,假设引入的 npm 包质量不够高,比如 node_modules 里面有 ES6 的语法,那么 webpack 在 uglify 阶段会报错!下面给出两种常见的出错场景:

ES6 的模板字符串

假设 node_modules 里面存在 ES6 的模板字符串语法,那么在生产环境打包的代码压缩阶段,UglifyJs 会抛出错误。

图片

ES6 的箭头函数

同样的,你使用 ES6 的箭头函数也是无法正常的压缩代码的。

图片

**细心的你一定会发现如果使用的是 webpack 4,这个场景描述的问题将不再出现。**webpack 4默认支持 ES6 代码的压缩,这个是什么原因呢?

初步分析

如果你有对 webpack 4 的依赖包进行过相关分析,比如直接查阅 package.json 文件或者通过 http://npm.broofa.com/ 网站上进行 webpack 依赖图分析。不难发现 webpack 4 里面使用了 terser-webpack-plugin 插件替代了之前一直使用的 uglifyjs-webpack-plugin 作为它的内置插件。

以 4.39.3 这个版本为例,可以看到它的 package.json 文件的依赖包括了terser-webpack-plugin。

图片

我们进一步分析发现 webpack 的 4.26.0 这个版本有一次提交,它的提交内容是对 webpack 内置插件进行了一次切换。

图片

经过这么一次分析,我们可以知道 webpack 4 之所以具备默认压缩 ES6 代码的能力,离不开 **terser-webpack-plugin **所起的作用!

进一步分析

在探究 terser-webpack-plugin 插件的原理前,我们先系统的回顾一下代码压缩插件的历史:

  • 当 uglifyjs-webpack-plugin 版本小于 v1.0 时,它使用的是 uglify-js 依赖
  • 但是 uglify-js 并不支持 ES6, 因此在 uglify-js 仓库的 harmony 分支 Fork 了一个 uglify-es
  • uglifyjs-webpack-plugin 的 v1.x 为了支持 ES6 的压缩语法,将 uglify-js 依赖切换到了 uglify-es
  • 但是 uglify-es 停止维护了: mishoo/UglifyJS#3156 (comment)
  • uglify-es 的停止维护导致了 terser 被 fork 出来了,并且 terser 处理了没有合入的 PRs,最终创建了一个独立的仓库: https://github.com/fabiosantoscode/terser
  • 随后,terser-webpack-plugin 被创建出来, 它基于 terser,并且具备uglifyjs-webpack-plugin 的同等功能 : https://github.com/webpack-contrib/terser-webpack-plugin
  • 由于 uglifyjs-webpack-plugin v2.x 回退到了 uglify-js, 不再支持 ES6。 因此那些希望支持 ES6 语法压缩的项目必须切换到 terser-webpack-plugin

备注:压缩插件历史的来源 webpack/webpack@311a728

到这里,我们可以得出一个基本的结论:terser-webpack-plugin 基于 terser 因此它具备 ES6 的压缩能力,uglifyjs-webpack-plugin v2.x 版本基于 uglify-js,无法支持 ES6 的压缩。

插件 依赖 是否支持 ES6(Y/N)
terser-webpack-plugin terser Y
uglifyjs-webpack-plugin v1.x uglify-es Y
uglifyjs-webpack-plugin v2.x uglify-js N

原理探究

代码压缩原理其实挺简单的,也是 AST 的一个经典的应用案例。它的压缩过程通常是:

     JS 源代码 -> AST -> 美化、压缩 -> 新的 AST -> 压缩后的代码 

了解了代码压缩的基本流程后,接下来我们看看源码包含了哪些内容,由于 terser 是从 uglify-es Fork 出来进行修改的,因此它的代码结构和 uglify-js 基本一致,只不过 terser 使用了 ES6 模块的静态分析功能。我们以 terser 的源码为例分析下:

  • ast.js:JS 的抽象语法树的描述信息
  • parse.js:Parser,用于从 JS 源代码分析出 AST
  • minify.js:用于将 AST 优化成更简短的结构
  • output.js:代码生成器,从 AST 输出 压缩后的代码,支持 sourcemap 的生成
  • propmangle.js:对变量的长度进行压缩,通常是单个字符
  • scope.js:分析变量定义/引用位置的信息
  • transform.js:节点遍历

然后,我们来一探 terser 和 uglify-js 的差异。对比了之后,发现一个很大的差异是 AST 的支持上面不同。

分析AST的差异发现,下面是两个文件 diff 对比只在 terser 中才有,而这些刚好对应 ES6 的语法。

AST_Arrow,
AST_Await,
AST_BigInt,
AST_Class,
AST_ClassExpression,
AST_ConciseMethod,
AST_Const,
AST_DefaultAssign,
AST_Destructuring,
AST_Expansion,
AST_Export,
AST_ForOf,
AST_Import,
AST_Let,
AST_NameMapping,
AST_NewTarget,
AST_PrefixedTemplateString,
AST_Super,
AST_SymbolMethod,
AST_TemplateSegment,
AST_TemplateString,
AST_Yield

至此,我们发现 webpack4 默认支持 ES6 压缩的关键是:terser 里面实现了 ES6 语法的 AST解析

开发模式首页运行报错

对nodejs和sql不太了解,我直接跑server和h5,首页打开的时候报错list.map is not a function,调查了一下,应该是调用goods接口时,后台返回的data不是一个数组 ,是一个对象导致的data: {errCode: "ECONNREFUSED", errMsg: "ECONNREFUSED"},请问我漏掉了什么?

关于正则匹配规则的代码缺陷问题

{
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },

如老师以上代码, 当我想要加上sass的支持的时候, 我马上增加了如下匹配规则

{
        test: /.s[ac]ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'sass-loader'
        ]
      },

但是在编译过程中, 发现scss后缀的文件会被匹配到css的规则上, 导致产生两次编译而报错, 错误如下

Didn't get a result from child compiler

debug了一下发现, 是因为两次匹配导致css的规则匹配错误, 导致编译产物为空造成的

因此建议修改一下/.css$//\.css$/, 如果需要使用sass, 则使用 /\.s[ac]ss$/,作为匹配规则, 避免正则下.未转义产生的问题

以上

关于publicPath和contentBase的问题

请教老师一个问题,关于output中的publicPath,还有devServer中的publicPath和contentBase作用总是有点分不清,能否帮忙讲解一下~

使用px2rem-loader构建失败

代码如视频中一样,结果编译时报错,错误如下:

ERROR in ./src/search.less
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/px2rem-loader/index.js):
Error: undefined:6:5: missing '}'
at error (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:62:15)
at declarations (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:260:26)
at rule (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:561:21)
at rules (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:118:70)
at stylesheet (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:81:21)
at Object.module.exports [as parse] (/Users/zhangyong/Desktop/webpack-demo/node_modules/css/lib/parse/index.js:565:20)
at Px2rem.generateRem (/Users/zhangyong/Desktop/webpack-demo/node_modules/px2rem/lib/px2rem.js:70:20)
at Object.module.exports (/Users/zhangyong/Desktop/webpack-demo/node_modules/px2rem-loader/lib/px2rem-loader.js:7:38)
at runLoaders (/Users/zhangyong/Desktop/webpack-demo/node_modules/webpack/lib/NormalModule.js:302:20)
at /Users/zhangyong/Desktop/webpack-demo/node_modules/loader-runner/lib/LoaderRunner.js:367:11
at /Users/zhangyong/Desktop/webpack-demo/node_modules/loader-runner/lib/LoaderRunner.js:233:18
at runSyncOrAsync (/Users/zhangyong/Desktop/webpack-demo/node_modules/loader-runner/lib/LoaderRunner.js:143:3)
at iterateNormalLoaders (/Users/zhangyong/Desktop/webpack-demo/node_modules/loader-runner/lib/LoaderRunner.js:232:2)
at Array. (/Users/zhangyong/Desktop/webpack-demo/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
at Storage.finished (/Users/zhangyong/Desktop/webpack-demo/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:43:16)
at provider (/Users/zhangyong/Desktop/webpack-demo/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:79:9)
at /Users/zhangyong/Desktop/webpack-demo/node_modules/graceful-fs/graceful-fs.js:90:16
at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.