搭错车的小火柴

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1.process.env.NODE_ENV

为什么我们在写前端代码的时候,可以使用 process.env.NODE_ENV 这样的代码(process 不是 node 模块么?为啥可以在浏览器下使用)?

因为webpack有DefinePlugin的存在,在初始模板的时候,注入了全局process对象,所以浏览器可以用process对象。

2.Buffer、setImmediate

为什么我们在写前端代码的时候,可以使用诸如 Buffer、setImmediate 等 node 才有的全局对象(https://nodejs.org/api/globals.html#globals_clearimmediate_immediateobject)

Buffer其实都是基于typedArray实现的,v8是支持typedArray的。在浏览器中使用Buffer、setImmediate,只需要引入polyfill。

3.production build

如果代码中出现了 if (process.env.NODE_ENV === 'development') { // do something },在 production build 的代码里面,会有这段代码么,为什么?

打包的时候,这段代码会被优化掉。因为在编译的时候,这段代码就类似于 if(false) {},webpack在编译的时候会对 if(false === false){} 或者 if (true === true){} 类似的代码做标记,然后terser会删掉这段逻辑。同样,在代码压缩minify的时候,也会把类似if ('a'=== 'a'){} 这些逻辑优化掉。

4.axios 同时支持了 node 和 browser 环境

axios 同时支持了 node 和 browser 环境,是怎么支持的?打包的时候,两个环境的代码都会打包进去么?

axios源码里面,有xhrAdapter和httpAdater,通过判断当前是浏览器环境还是node环境,来决定使用哪个adapter。打包的时候,也只会把当前环境的adapter打包进去。

 5.sockjs实现webpack热更新原理

sock-node 建立全双工低时延的websocket通信,来实现HTMLModuleReplacement,就是通知sock-client的dev-server代码发生了改动。

当代码发生更新后,本地的dev-server会重新编译run,然后生成热更新的.json文件推送给浏览器端展示。每次修改代码,紧接着触发重新编译,然后浏览器就会发出 2 次请求。请求的便是本次新生成的 2 个文件。
首先看json文件,返回的结果中,h代表本次新生成的Hash值,用于下次文件热更新请求的前缀。

 

c 表示当前要热更新的文件对应的是index模块。假设c是{ need-index-module:true }

 

 

新的Hash值:2536e910768ae4c9b393
新的json文件: 2536e910768ae4c9b393.hot-update.json
新的js文件:need-index-module.2536e910768ae4c9b393.hot-update.js

webpack负责监听文件是否变化,websocket只是实现双工通信,告诉浏览器啥时候请求。

 

 

https://juejin.im/post/5de0cfe46fb9a071665d3df0
https://segmentfault.com/a/1190000020310371

为什么代码的改动保存会自动编译,重新打包?这一系列的重新检测编译就归功于compiler.watch这个方法了。监听本地文件的变化主要是通过文件的生成时间是否有变化,比如fs.watch(sourceDir……),就可以监听到本地某个文件夹下文件的变化。

为什么在开发的过程中,你会发现dist目录没有打包后的代码,因为都在内存中。原因就在于访问内存中的代码比访问文件系统中的文件更快,而且也减少了代码写入文件的开销,这一切都归功于memory-fs。

6. vendor chunk

vendor: 小贩;摊贩;(某种产品的)销售公司;(房屋等的)卖主

webpack4之前,大家用CommonsChunkPlugin做code-split:详解CommonsChunkPlugin的配置和用法:https://segmentfault.com/a/1190000012828879
webpack-4之后,大家用splitChunkPlugin:https://juejin.im/post/5af15e895188256715479a9a

如何按需切割加载模块:https://webpack.docschina.org/api/module-methods/#import

7.优化打包模块的体积和命名方式(demo)

// vue.congif.js 示例
config.optimization.splitChunks({
            automaticNameDelimiter: '-', // chunk命名用-隔开,默认好像是~
            cacheGroups: {
                vendor: {
                    minSize: 0,
                    test(chunk) {
                        return ( // vue的单独打包
                            /node_modules/.test(chunk.resource) &&
                            ['/vue/', '/vue-router/', '/vuex/'].some(key =>
                                chunk.resource.includes(key),
                            )
                        );
                    },
                    name: 'vendor',
                    chunks: 'all',
                    enforce: true,
                },
                common: {
                    minChunks: 2,
                    maxAsyncRequests: 2,
                    maxInitialRequests: 2,
                    name: 'common',
                    chunks: 'all',
                    enforce: true,
                },
            },
        });

优化前:                                    优化后:

   

 

config.optimization.splitChunks({
            automaticNameDelimiter: '-', // chunk命名用-隔开,默认好像是~
            cacheGroups: {
                vendor: {
                    minSize: 0,
                    test(chunk) {
                        return (
                            // vue的单独打包
                            /node_modules/.test(chunk.resource) &&
                            ['/@vue/', '/vue-router/', '/vuex/'].some(key =>
                                chunk.resource.includes(key),
                            )
                        );
                    },
                    name: 'vendor',
                    chunks: 'all',
                    enforce: true,
                },
                uiLibs: {
                    name: 'chunk-elementUI-libs',
                    test: /node_modules\/element-ui/,
                    priority: 10,
                    chunks: 'initial',
                },
                antV: {
                    name: 'chunk-antv',
                    test: /node_modules\/@antv/,
                    priority: 10,
                    chunks: 'initial',
                },
                common: {
                    minChunks: 2,
                    maxAsyncRequests: 2,
                    maxInitialRequests: 2,
                    name: 'common',
                    chunks: 'all',
                    enforce: true,
                },
            },
        });

8.snowpack和ESM import

  • 对于webpack,更改一个文件,需要把这个文件相关的文件(chunk)都重新编译并打包,当项目越庞大,涉及的chunk越多,打包时间越长
  • 而基于ESM的snowpack,修改任何组件都只需做单文件编译,并且每个编译过的文件会被独立缓存,只要文件没改过就永远不会rebuild,速度大大加快

 9.找时间研究rollup

10.sourcemap

https://www.cnblogs.com/axl234/p/6500534.html
sourcemap是为了解决开发代码与实际运行代码不一致时帮助我们debug到原始开发代码的技术。eval和source-map都是webpack中devtool的配置选项, eval模式是使用eval将webpack中每个模块包裹,然后在模块末尾添加模块来源//# souceURL, 依靠souceURL找到原始代码的位置。包含eval关键字的配置项并不单独产生.map文件(eval模式有点特殊, 它和其他模式不一样的地方是它依靠sourceURL来定位原始代码, 而其他所有选项都使用.map文件的方式来定位)。包含source-map关键字的配置项都会产生一个.map文件,该文件保存有原始代码与运行代码的映射关系, 浏览器可以通过它找到原始代码的位置。

devtool: env === 'production' ? 'source-map' : 'module-eval-source-map'

所以在production环境是只能看到source-map,看不到eval-source-map。

9.webpack-bundle-analyzer

在vue-cli的vue.config.js中配置:webpack-bundle-analyzer

chainWebpack: config => {
        process.env.npm_report_event === 'analyzer' &&
            config
                .plugin('webpack-bundle-analyzer')
                .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin);
    },

然后执行 yarn report ( "report": "npm_report_event=analyzer vue-cli-service build" ),就可以在控制台看到打包分析结果。 

 执行 yarn report --report ,就可以在浏览器看到打包分析结果。 

 

posted on 2020-08-11 18:39  搭错车的小火柴  阅读(70)  评论(0编辑  收藏