环境分离
像我们之前配置都是些在webpack.config.js文件的,但是比如开发环境下,某些配置是不需要的,如插件。生产模式下我们的devServe的配置也是不要的。所以现在我们把webpack.config.js分离成三个文件,一个是开发的,一个是生产环境的,一个是公共的。
另外我们执行npm run serve也需要配置,因为默认是会找到package.json所在的目录下的webpack.config.js文件去执行。
在配置后面加上–config 再加上文件名即可。这样就会找到在package.json文件下的config里面的配置文件。
(改错,下图的输出应该都是…/build)
这个变量以后做判断用的
还有另一种写法,就是我们要引用公共文件common.js加载时,
可以在传入的参数env里面拿到development,若是development,则为true, 否则为undefined,而undefined在大多数条件情况下都是转为false。
这两种方式都可以,第一种就是手动给变量isproduction添加ture/false。 第二种就是通过公共文件common,传入的env,来判断。
我们应该发现,输出的文件路劲要带…/,而输入的文件路径依旧是./src,这是因为entry的相对路径,不是相对于当前文件的目录的,而是相对于content配置属性。
content加的是绝对路劲,这样src的相对路劲就会依据这个绝对路劲去找。当我们不写的时候,默认是package.json的启动路劲,比如我们之前写了 --config ./config/xxx,这里的启动路劲就是config,所以在config所在的目录下是能找到src的。
配置文件的分离
将公共的代码抽离到Common去,相对应的代码抽离到相对应的文件。也可以都写在一个文件,然后用我们传入的env来判断是哪个环境,然后做判断来配置插件就行。
这里我们用第一种,代码抽离,可以注意到,很多文件的路劲,应该修改了,如输出的文件夹,应该加上…/,但是每个都这样写太麻烦,很多脚手架的解决措施是
自己配置一个路劲函数,解决路劲问题,使用如下图
另外还有一些babel文件的配置也需要分离比如![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/bc2af11f9f2eac6fbe44c76af6aebc2e.png)
这个插件主要是用来热替换的,所以在生产模式下也是不需要的。
所以我们要想办法在这个文件拿到我们现在是什么环境。
其实当我们设置mode的时候,webpack默认就帮我们配置了process.env.NODE_ENV这个值。也就是说在源代码里面,我们可以通过代码取出这个值,生产是production,开发是development。但是babel.config.js不是我们的源代码,不能直接取这个值。
我们直接在最外层的common去设置这个值,因为babel.config.js文件是当解析到babel时才去执行的,也就是他是在这个上下文的,或者在这个上下文的下一层,而作用域链是往上的,所以可以在babel,config.js文件中拿到我们设置的这个值。
这样我们就分离好了,但是分离好还要合并,因为common必须根据环境的不同搭配不同的dev或者prod文件。
webpack官方推荐使用的是webpack-merge这个库。
cnpm install webpack-merge -D
合并完成。根据当前环境合并不同文件。
这里要注意一个小细节。
当我们如果是开发环境下,isProcution是undefined,但是传给process.env.proctuions后会变成字符串的undefined,这时候字符串的取反就是false。应该是Node的特性,所以我们做判断要注意下。
这样就正确了。
代码分离
现在我们的bunle.js文件是全部代码都在里面的,一般开发我们是要分离这个文件为几个小文件,然后按需加载,这样也能提高性能。
webpack常用的方法有三种:
1 入口起点,使用entry配置手动分离代码
2 防止重复 使用Entry Dependencies 或者 SplitChunksPlugin去重和分离代码
3 动态导入 通过模块的内联函数调用来分离代码。
比如我们要对这两行代码进行分离。第一种方法: entry
先将文件进行分离,
entry可以传入一个对象,按需引入,然后打包的文件根据name不同打包出不同的文件,可以看到打包生效了。这也是webpack的第一种方式分离代码。
第二种 代码重复
我们如果两个文件都引入了同一个库,那么到时候打包的时候,两个js文件都会有loadsh的源码,这样显然是不行的。
第一种办法:Entry Dependencies(不推荐)
还是在entry那里修改,给添加的模块独立生成一个包,然后使用的模块要dependOn。这样就可以正常使用了。
如果依赖的是一样的,可以这样写。
那如果我们有很多依赖的模块呢,这样写未免太麻烦。
第二种 splitChunks
这种主要是依赖一个SplitChunksPlugin的插件,并且webpack内容已经帮助我们实现了,所以我们只需要配置信息就行。
这个是在optimization(优化相关的配置)里面处理的,如图
chunks一般有三个值,默认是async , 还有Initial, all,我们开发一般都是使用all。build之后可以看到,代码也是做了分离。多了个952.bundle.js。
splitChunks除了chunks属性外,还有几个常用的属性。
在开发过程中,我们一般只设置chunks为all,若想打包单独的文件则设置cacheGroups,其他的一般使用默认,所以也不用全部记住,了解就行。
这是vue3的设置,可以看到他把打包的第三方库放到了chunk-vendors文件去了,然后只打包同步的代码,优先级为-10.name的话是固定的,而filename可以设置动态的名字。
动态导入(dynamic import)
像vue3, 同步的代码一般设置到mian.bundle.js,第三方库的放在chunks-vendor.js,若引用了多次的会打包到common-chunks.js文件,还有可能打包到runtime.js文件。
但是异步的代码,webpack会帮我们分离,(import异步导入的时候).webpack提供了两个实现动态导入的方法
1 使用es6的import()语法 推荐 ,如 import(’./xxx’).then(res=>res是导出的对象)
2 使用webpack遗留的require.ensure 不推荐
只要使用了动态导入,不管文件大小,不管设置了chunks设置了initial还是async,都会单独拆分一个文件。
一个是主要的打包文件,另外两个是我用异步导入的方式,webpack两个都拆分出来了。
可以看到我们的代码是以什么985等等开头的,为什么呢?webpack默认会以output的filename来设置名字,并且我们可以通过optimizations.chunkIds来设置生成文件的名字的算法,如图
将chunkIds的值设为自然数,大暴出来的就是1234等等。自然数不利于浏览器缓存。还可以设置named(开发环境推荐),生成的名字就是路劲+文件名
还有deterministic,(生成id,针对相同的文件生成的id是不变的。)这个就是默认配置,我们上面出现的985这写,就是这个值设置的。(生产环境推荐)
动态导入chunkName的命名
一般我们的主要代码文件叫Bundle,但是其他的异步加载的文件一般叫chunk.js,我们可以通过output.chunkFilename来配置,
这个name怎么设置呢,
在异步导入的时候使用魔法注射,让webpack知道应该起什么文件名,webpackChunkName:xxx
像我们之前vue的路由设置,异步加载组件,达到懒加载
就是通过 const XXX = () => import(’./xxx’) ,返回一个promise
vue的官方也是这样设置的。