《Webpack》彻底入门Webpack(二)(1)

环境

============================================================

概述


环境主要分为:开发模式和生产模式,在不同的场景下可能需要不同的配置,使用不同的功能,所以要区分环境

  • **开发模式:**会额外的用到一些调试功能,比如webpack-dev-server,source-map,代码风格检查,但为了加快调试速度,可能不会用上压缩等;

  • **生产模式:**项目上线即将上线了,因此打包的重点是减少文件体积,图片压缩,转base64,提取公共代码,tree-shaking等功能,但是如webpack-dev-service或者eslink这样的调试工具就不再需要了;

打包的时候可以通过–env告诉webpack需要什么环境,比如:

//打包的时候通过–env命令告诉webpack现在是什么环境

//envname就是环境名

webpack --env envname

配置


首先看一下这个

module.exports = env => {

console.log(env)

var common = {

enrty:{

app:‘./app.js’

},

output:{

filename:‘bundle.js’

},

module:{

rules:[]

},

plugins:[]

}

return common;

}

这个和前一篇文章中的格式有所差别,前一篇中明明导出的是一个对象,而这里是一个函数,在函数中返回了一个对象,效果其实是一样的,最终导出的都是对象;

这样写有一个好处,就是可以接收参数了,上文中通过–env进行打包的时候,就可以读取到后面跟着的值,比如

//执行打包

webpack --env development

当执行打包之后,前面的env的值就会变成development,既然可以获取到值,那么就可以根据值的不同判断最终打包需要按照哪个规则进行打包,另外插一句,既然是通过值判断打包的最终配置,那么实际上不仅仅是可以区分开发环境还是生产环境,人任意多的环境也是可以的,不过就一般而言开发环境和生产环境就可以了;

配置的时候需要考虑到有些loader,插件不管是开发模式还是生产模式都需要使用到,比如,css-loader,babel-loader;

因此环境配置文件大概可以分为三个:开发环境下的配置文件,生产环境下的配置文件,基础配置文件,之后判断env的参数,合并对应的配置就达到了配置环境的目的;

基础配置文件

其实这个文件就是配置文件主体,也就是webpack.config.js,又或者是其他指定的配置文件,与之前的不同的是:一个导出的是函数,通过参数值判断需要合并的环境,一个是需要引入webpack-merge,这个是一个合并工具,需要通过npm安装

//安装webpack-merge

cnpm install webpack-merge --save

安装好后,基础配置文件也就是webpack.config.js文件

const pro = require(‘webpack’);

const extarctTextCss = require(‘extact-text-webpack-plugin’);

//这个是合并的插件,需要通过npm安装

const merge = require(‘webpack-merge’)

//引入环境配置文件

const dev = require(‘./webpack.dev.js’)

const pro = require(‘./webpack.pro.js’)

module.exports = env => {

var common = {

entry:{

app:‘./app.js’

},

output:{

filename:‘bundle.js’,

path:__dirname+‘/src/mybundle’

},

//写入通用的loader

module:{

rules:[

]

},

//它是一个数组

plugins:[

new extarctTextCss({

filename:env === ‘production’?‘app.bundle.css’:‘app.dev.css’

})

]

}

//原版

// return common;

//改写后,将不再直接返回common,而是返回合并后的文件

//第一个参数是基础配置对象,第二个参数通过判断参数的值,决定是生产环境还是开发环境的配置文件

return merge(common,env===‘production’?pro:dev);

}

到这里,就可以使用命令打包了

//打包默认文件+开发环境

webpack --env development

//指定配置文件+指定开发环境

webpack --config webpack.common.js --env development

//指定配置文件+指定生产环境

webpack --config webpack.common.js -env production

但是每次这么打包有点繁琐,所以在package.json对命令进行简写

//在package.json文件里,将命令简写成自定义命令

“scripts”: {

“test”: “echo “Error: no test specified” && exit 1”,

“bulid”: “webpack --env production --config webpack.common.js”,

“dev”:“webpack-dev-server --env development --config webpack.common.js”

},

在执行npm run build的时候,自动执行了打包生产环境的代码,在执行npm run dev的时候,自动执行打包开发环境,这样就简单多了;

基础文件中环境配置+小结

那么,新问题又出现了,如果在基础配置文件里的通用loader,也需要根据环境的不同,配置不同的插件,比如poster-loader,这个loader是一个平台loader,需要根据不同的环境区分不同的配置怎么办?

其实一样的,而且务必记住,webpack.config.js这个文件本质上就是一个js文件,只不过这个js文件的属性名,值是需要按照webpack规定的格式书写,既然是js文件,那么完全不必要考虑太多,写js语法就可以了;

比如这个postcss-loader

use:[

{

loader:‘postcss-loader’,

options:{

ident:‘postcss’,

//使用三元运算符

plugins:env===‘production’?[

//自动补全前缀插件

require(‘autoprefixer’)({

‘overrideBrowserslist’:[

“>1%”,“last 2 versions”

]

}),

//自动使用下一代语法插件

require(‘postcss-cssnext’)(),

//自动合并成精灵图插件

require(‘postcss-sprites’)({

spritePath:‘dist/sprite’,

retina:true

})

]:

[

//自动补全前缀插件

require(‘autoprefixer’)({

‘overrideBrowserslist’:[

“>1%”,“last 2 versions”

]

}),

//自动使用下一代语法插件

require(‘postcss-cssnext’)()

]

}

},

]

plugins中值既然是一个数组,数组中的每一项都是需要引入的插件,那么是不是可以通过三元运算符直接去判断参数是不是生产环境,甚至,可以把这个值单独提取到外面,在一开始的时候就判断是不是生产环境,比如

module.exports = env => {

//直接判断是不是生产环境

let production = env === “production”?[]:[]

var common = {

enrty:{

app:‘./app.js’

},

output:{

filename:‘bundle.js’

},

module:{

rules:[]

},

plugins:[]

}

return common;

}

在开头判断好了之后,使用的时候直接赋值就好了

use:[

{

loader:‘postcss-loader’,

options:{

ident:‘postcss’,

//使用三元运算符

plugins:production

}

},

]

包括开发环境文件和生产环境文件,其实如果愿意在一个文件里处理,那不分也没有问题,也不需要引入merge,直接判断参数,然后再决定需不需要将值加上就可以了;

开发环境文件

开发环境文件示例

const webpack = require(‘webpack’);

module.exports = {

devtool:‘cheap-module-source-map’,

devServer:{

port:9001,

overlay:true,

hot:true,

hotOnly:true

},

plugins:[

new webpack.HotModuleReplacementPlugin(),

new webpack.NamedModulesPlugin()

]

}

生产环境文件

生产环境示例

const webpack = require(‘webpack’);

var htmlWeboackPlugin = require(‘html-webpack-plugin’);

module.exports = {

optimization:{

minimize:false

},

plugins:[

new htmlWeboackPlugin({

filename:‘index.html’,

template:‘./index.html’,

minify:{

collapseWhitespace:true

},

inject:true

})

]

}

webpack4中的环境区分


在webpack4中,对环境的区分更简单了,官方对其集成了loader,比如

//打包命令

webpack --mode production/development/none

只需要运行命令–mode,并且跟上指定模式,webpack会自动以一些固定的模版运行打包,比如指定–mode production(生产模式),即使我们在配置文件中没有编写:压缩,tree-shaking等插件,但是webpack依旧会帮忙去使用这个功能;

**

另外,在webpack4中是需要加上mode属性的,否则在执行打包的会出现警告提示,当然要是无视也没上面关系,加上mode之后,就不需要指定上面的关键词了,官方也是比较推荐写入mode,比如

module.exports = env => {

var common = {

mode:‘development’,//或者production,生产模式

enrty:{

app:‘./app.js’

},

output:{

filename:‘bundle.js’

},

module:{

rules:[]

},

plugins:[]

}

return common;

}

当指定了mode为development之后,执行打包的时候,直接输入webpack,此时打包的方式等同于输入了

webpack --mode development

dev-server模拟线上环境

==========================================================================

先说个简单的例子,跨域,尤其是使用Vue的时候,当我们把模版样式写好,需要对接接口的时候,如果直接启动vue项目,那么就会报跨域错误,因为本地调试的域名是loaclhost,与服务器的接口的域名不一致,此时就没有办法正常连调项目;在webpack中就内置了解决这些问题的方法;

安装


也有全局和局部之分,但是通常我们都是在package.json中配置webpack-dev-server,因此通常使用的是局部安装

//在 项目的根路径下

cnpm install webpack-dev-server --save

配置


在webpack.config.js等配置文件中,与entry,output这些同级属性中加入devServer属性,比如

module.exports = env => {

//直接判断是不是生产环境

let production = env === “production”?[]:[]

var common = {

enrty:{

app:‘./app.js’

},

output:{

filename:‘bundle.js’

},

module:{

rules:[]

},

plugins:[],

//在webpack.config.js或其他指定配置文件中配置webpack-dev-server

//webpack-dev-server配置

//固定对象的key为:devServer,值是一个对象

devServer:{

//端口

port:9001,

//默认是true,一般不用管,是开启浏览器上当前页面的状态

inline:true,

//开启遮罩,具体效果就是vue那种错误遮罩

overlay:true,

//路径重定向,假如页面的路径是错误的,如果未开启,会提示路径错误,找不到页面

//重定义了之后,如果路径错误,那么会仅会停留在当前页面,不会跳转

// histroyApiFallback:true,

///路径重定向进一步使用

historyApiFallback:{

//定义路径,值是一个数组,数组的每一个值代表了一个路径规则

rewrites:[

{

//使用正则匹配

from:/^/([-~])/,

//重定向路径

to:function(context){

return ‘./’+context.macth[1]+‘.html’

}

}

]

},

//代理接口

proxy:{

// '/'代表,碰到以 / 开头的地址就进行代理转发

‘/’:{

//转发的目标地址

//这里也就写上了接口的服务器地址,解决跨域不是同源的问题

target:‘’,

changeOrigin:true,

//重写地址,简化路径名

pathRewirte:{

//key:如果路径中有以/comments的路径地址

//value:改写为/api/comments

//这样就可以大大的减少路径名了

‘^/comments’:‘/api/comments’

},

//代理的请求头

headers:{

}

},

//多个就写多个规则对象

‘/smart’:{

}

},

//热更新

hot:true, //开启热更新

hotOnly:true, //仅仅使用热更新,不使用其他

}

}

return common;

}

值的注意的是,热更新hot和extact-text-webpack-plugin这个插件是不相互兼容的,因此需要把extact-text-webpack-plugin这个插件的注册状态中的disable,设置为true,表示禁用插件;

source-map追踪错误

========================================================================

概述


简单的说,source-map为了方便调试,我们需要知道打包后的代码对应于原文件的位置,因为打包后代码都是被压缩过了,如果线上报错了,根本查不到报错的位置,因为所有关联的js最终都会被合并成一个js文件;

配置


source-map不需要安装,直接开启就好了,它也是和entry,output这些同级,值是规定好的,不同的值代表不同的含义

//开启source-map

devtool:‘eval-source-map’,

//webpack-dev-server配置

devServer:{

},

//它是一个数组

plugins:[

]

开发模式

开发模式下最常用的就这几个

  • eval:构建最快,只能定位到打包后的代码。适用度:无需source-map

  • eval-source-map:构建较快,生产一个dataUrl形式的sourcemap。适用度:需要简单的调试

  • cheap-eval-source-map:构建快,重新构建慢,定位到转换后的代码。适用度:较为详细的调试

  • cheap-module-source-map:构建慢,重构快,能定位到原代码。适用度:开发过程中一般用这个

生产模式

  • source-map:构建和重构都很慢,能定位原始代码。适用度:上线后一般用这个

  • hidden-source-map:候检和重构都很慢,能定位原始代码,但不追加注释。适用度:一般不使用

  • nosource-source-map:构建和重构都很慢,不能定位到源码。适用度:一般不使用

打包优化

==============================================================

代码分割


概述

代码分割的目的为了减少加载代码大小提取公共资源,减少加载次数做的优化;比如,多页面项目中,a页面和b页面都引入了jq,那么正常情况下,jq会被打包2次,这显然是不合理,jq只需要单独提取出来后打包一次就够了,没有必要混入在a,b中被打包两次;

使用到的webpack的核心功能:optimization,关于这个功能,具体可以查看官网核心功能optimization介绍,或者核心功能optimization介绍

注意,版本差异:webpack3中使用:commonChunksPlugin,而在webpack4中使用optimization下的SplitChunks,下例以webpack4为主

多页面打包

多页面优化的核心概念,就是提取公共依赖,把几个页面中都用到的依赖给打包为一个单独文件,这样a页面在浏览器被加载完之后,打开了b页面,因为b页面也使用到了这个相同的依赖,因此b页面的打开速度会非常快;

因此,多页面应用一般会这么打包:主页面代码+公共依赖+第三方包+webpack运行代码;

//这个插件是一个辅助性的,作用是删除上一次打包的代码,有时候会遇到上次打包的代码没有被删除

const {CleanWebpackPlugin} =require(‘clean-webpack-plugin’)

module.exports = {

mode:‘development’,

entry:{

a:‘./a.js’,

b:‘./b.js’

},

output:{

filename:‘./[name].[hash:4].min.js’

},

module:{

rules:[]

},

optimization:{

//使用webpack4中的splitChunks

splitChunks:{

name:true,

//优化的类型,all代表所有的都进行优化打包

chunks:‘all’,

//设定公共依赖提取最低大小,小于这个值的公共依赖将不会被提取出来,10000=10kb

minSize:10000,

//缓存组,用于设定指定打包

cacheGroups:{

//打包命名为m2

m2:{

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
pment’,

entry:{

a:‘./a.js’,

b:‘./b.js’

},

output:{

filename:‘./[name].[hash:4].min.js’

},

module:{

rules:[]

},

optimization:{

//使用webpack4中的splitChunks

splitChunks:{

name:true,

//优化的类型,all代表所有的都进行优化打包

chunks:‘all’,

//设定公共依赖提取最低大小,小于这个值的公共依赖将不会被提取出来,10000=10kb

minSize:10000,

//缓存组,用于设定指定打包

cacheGroups:{

//打包命名为m2

m2:{

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-Nu4a1wks-1715721917324)]

[外链图片转存中…(img-KOomnLJ1-1715721917324)]

[外链图片转存中…(img-LKtibLcR-1715721917325)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值