还在为webpack的配置而烦恼吗?这里有一份webpack从简易到高级版本的配置。还附赠配置地址,你想要吗?不,你不想。老老实实自己配置去吧。

压箱底的笔记而已,大家看看乐乐就好了,这是笔者为了练习webpack而尝试了不同的配置方式,参考了create-react-app的webpack配置。以及学习了如何自己写一个简易的proxy。

Loaders全配置

Loader 作用
html-loader ---
html-webpack-plugin ---
style-loader ---
mini-css-extract-plugin 划重点,webpack4.0之后不再使用extract-text-webpack-plugin
css-loader 一个将CSS变成JS的loader,笔者认为它的modules模块化是一个很实用的功能,大爱
sass-loader 一个SASS的处理器,先将scss编译成css,然后css再做进一步的处理
node-sass 编译scss依赖的包
postcss-loader 一款配合autoprefix,autoprefixer.github.io/ 自动给CSS加恼人的前缀
ts-loader 如果不用babel编译ts,则需要ts-loader
file-loader 导入文件,比如json,变成js的格式
url-loader 类似于file-loader,不过比file-loader智能,在文件过大的情况下可以只加载一个地址,而不用将文件载入
babel-loader 别说了,es6就需要他编译
webpack 大家都懂的,核心
webpack-cli 有了启动编译变得简单

babel配置

现在二进制可以直接编译js

npx babel src --out-dir lib
复制代码

大声告诉我Babel是干什么的? ——因为JS语法一直在修订进步,而用户使用的浏览器更新频率不如JS语法更新的快,因此需要一个编译JS语法,使兼容支持不同时期JS语法的浏览器。

npm install --save-dev @babel/core @babel/cli @babel/preset-env
npm install --save @babel/polyfill
npm install --save-dev bable-loader
复制代码
@babel/polyfill vs @babel/preset-env
无视语法,直接require缺失api 救得了各种新颖写法(如箭头函数),救不了api
核心包core/js

@babel/preset-env

babel-preset-es2015
babel-preset-es2016
babel-preset-es2017
babel-preset-latest
A combination of the above ^
....
复制代码

噩梦般的配置,刚学习babel的时候,看到这些配置,隐约觉得自己学不会了。但是现在babel-preset-env就可以搞定所有了!。

@babel/plugin-proposal-class-properties babeljs.io/docs/en/bab…

@babel/polyfill

这个包已经被babel给移除了,它仅仅是core-js的别名。

其他plugin

REACT全配置

多安装一个babel即可


npm install --save-dev @babel/preset-react
npm install --save-dev react react-dom
复制代码

TS全配置

npm install --save-dev typescript
复制代码

ts可以用babel编译

npm install --save-dev @babel/preset-typescript
复制代码

ts也可以用ts-loader编译,需要配置tsconfig.js

npm install --save-dev ts-loader
复制代码

有关CSS加载的一些见解

CSS loader可以很简单,也可以相当复杂,一般的需求有以下几点:

  • 有效CSS,直接inline的加载
  • 希望可以单独生成一个文件,然后url加载
  • 希望可以压缩一下
  • 想要自动加前缀的功能
  • 使用SCSS等,高级CSS处理器

参考create-react-app的配置文件,写的一个一本满足的css loader大餐:

// mini-css-extract-plugin,有了他可以代替style-loader,不仅压缩了文件,还可以帮助我们将CSS从js中剥离出来
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//loaders的主体,按照loader的顺序应该是先是预处理,比如Scss,然后是加前缀prefix,到此为止大家还是CSS的样子,等到了css-loader,css就变成了js,最后style-loader或者minicss将css模块再变成js生成文件或者内联。
const getStyleLoaders = (cssOptions, preProcessor,env) => {const loaders = [// 此处是最后一步,将CSS提取出或者内联{loader:env==="development"?require.resolve('style-loader') : MiniCssExtractPlugin.loader},// 此处将CSS变成标准的JS模块,如果有css模块化的需求,是在此处理{loader: require.resolve('css-loader'),options: cssOptions,},// 此处将CSS预处理处,一般是给css加上恼人的前缀,这里可以设置浏览器的版本,你需要哪些浏览器的支持{loader: require.resolve('postcss-loader'),options: {ident: 'postcss',plugins: () => [require('postcss-flexbugs-fixes'),require('postcss-preset-env')({autoprefixer: {flexbox: 'no-2009',},stage: 3,}),],},},];// 此处如果有sass等预处理的需求,需要在此配置if (preProcessor) {loaders.push(require.resolve(preProcessor));}return loaders;
};
// style files regexes,这里是为了避免重复配置css的各种类型
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;// 导出给webpack配置使用
module.exports={getStyleLoaders,cssRegex,cssModuleRegex,sassRegex,sassModuleRegex}复制代码

HMR热更新配置——减少手动编译刷新页面

webpack自带的服务器

npm install --save-dev webpack-dev-server
复制代码
devServer: {contentBase: path.join(__dirname, 'dist1'),compress: true,hot: true,port: 9000
},
entry: [require.resolve('webpack-dev-server/client') + '?/',require.resolve('webpack/hot/dev-server'),path.resolve(__dirname,'src/index')
],
plugins: [new webpack.HotModuleReplacementPlugin()
]
复制代码

webpack自带的服务器的跨域问题

devServer: {proxy: {'/slider': {target: 'http://www.cherryvenus.com/',secure: false,changeOrigin: true//important 能解决大多数404无法访问的问题}}
},
复制代码

自定义服务器

npm install --save-dev express webpack-hot-middleware webpack-dev-middleware
复制代码

client,webpack,此处不能忘,其实就是一个链接websocket的一个类似于插件的程序,记得production的时候将此处移除,不然bundle会很大呢。

entry: [require.resolve('webpack-hot-middleware/client') + '?path=/__what&timeout=2000&overlay=false',path.resolve(__dirname,'src/index')
],
plugins: [new webpack.HotModuleReplacementPlugin()
]
复制代码

server,此处的path配置需要和客户端的path一致。

app.use(require("webpack-hot-middleware")(compiler,{log: false,path: "/__what",heartbeat: 2000
}));
复制代码

entry入口的client添加模块,不accept,程序无法自动刷新。

if(module.hot){module.hot.accept()
}
复制代码

http-proxy-middleware——解决开发中的跨域问题

npm install --save-dev http-proxy-middleware
复制代码
var proxyMiddleWare = require("http-proxy-middleware");
var proxyPath = "http://www.cherryvenus.com/";
var proxyOption ={target:proxyPath,changeOrigoin:true};
app.use(proxyMiddleWare("/slider",proxyOption))
复制代码

压箱底的proxy研究

基于第三方插件的proxy配置开发

无论是http-proxy-middleware还是webpack-dev-server的proxy都是基于http-proxy-middleware,而http-proxy-middleware是基于node-http-proxy。

参考网址:

github.com/nodejitsu/n…

github.com/chimurai/ht…

var proxyPath = "http://www.cherryvenus.com/";
var proxyOption ={target:proxyPath,changeOrigin:true,selfHandleResponse : true,ignorePath:true};
const proxy = httpProxy.createProxyServer({})//如果selfHandleResponse为true就是可以自己修改获得的内容,如果不需要修改就是获取转发就无需设置了。// 如果想要自定义获取到的内容,则可以通过触发这个事件`proxyRes`来截获内容并修改proxy.on('proxyRes', function (proxyRes, req, res) {var body = new Buffer('');// 这里笔者复制了header信息,省去了一波配置for(let i in proxyRes.headers){res.setHeader(i, proxyRes.headers[i]);}proxyRes.on('data', function (data) {body = Buffer.concat([body, data]);});proxyRes.on('end', function () {body = Buffer.from(body);res.write(body);res.end()res.rs()});proxyRes.on('error', function (err, req, res) {res.writeHead(500, {'Content-Type': 'text/plain'});res.end('Something went wrong. And we are reporting a custom error message.');});
})// 此处仅仅是配置了一个链接而已,真正触发代理,是下方的proxy.web(req, res, proxyOption);app.use("/slider/",(req, res, next)=>{// 当地址地位到let p= new Promise((rs,rj)=>{// 先关闭之前的代理,如果有proxy.close();res.rs=rs// 请求一个新的链接proxy.web(req, res, proxyOption);})p.then(()=>{next()})return p
})
复制代码

手动写一个

看到上面的解决方法,突然灵光一闪,那么我是不是可以自己写一个呢?这个流程并不复杂,其实代理就是抓取网页然后转发的过程,既然如此,写一个简易的proxy并不是什么难事。

const http=require("http")
// 创建服务器
http.createServer({ host : 'localhost'}, (req, res) => {// 打开一个请求http.get('http://www.baidu.com', (res1) => {// 抓取内容var body = new Buffer('');res1.on('data', (chunk) => { body = Buffer.concat([body, chunk]);});res1.on('end', () => {body = Buffer.from(body);// 复制头部信息for(let i in res1.headers){res.setHeader(i, res1.headers[i]);}// 返回内容,代理成功res.write(body);res.end();});})
}).listen(8000);
复制代码

代理就是如此简单,当然这只是一个原理,一种实现方法,就是抓取网页再打印到页面上。

然后笔者在查阅node中http发现一个惊为天人的写法(也许是笔者见识浅薄),一个利用了Http的method为CONNECT的方法,将当前链接处于链接状态,也就是不会断,然后用 net.connect这个方法,链接到了请求链接,建立了互读互写的管道。

const http=require("http")
const net=require("net")
const url=require("url")
const proxy = http.createServer((req, res) => {const options = {port: 1337,host: 'localhost',method: 'CONNECT',//会触发"connect" https://nodejs.org/api/http.html#http_event_connectpath: 'www.baidu.com:80'};const req1 = http.request(options);req1.end();req1.on('connect', (res1, socket, head) => {let context=new Buffer("")// make a request over an HTTP tunnelsocket.write('GET / HTTP/1.1\r\n' +'Host: www.baidu.com:80\r\n' +'Connection: close\r\n' +'\r\n');socket.on('data', (chunk) => {context = Buffer.concat([context, chunk]);});socket.on('end', () => {for(let i in req.headers){res.setHeader(i, req.headers[i]);}context=context.toString().split("\n\r\n")context.shift()res.end(context.join(""))});});
}).listen(1337);
proxy.on('connect', (req, cltSocket, head) => {const srvUrl = url.parse(`http://${req.url}`);const srvSocket = net.connect(srvUrl.port, srvUrl.hostname)cltSocket.write('HTTP/1.1 200 Connection Established\r\n' +'Proxy-agent: Node.js-Proxy\r\n' +'\r\n');srvSocket.write(head);//管道建立了互读互写srvSocket.pipe(cltSocket).pipe(srvSocket)
});
复制代码

这个方法的简易原理是这样的,当你访问http server的时候,http server调起了一个访问自身链接,并且设置method为CONNECT,也就是不间断的意思,并创建了一个clientSocket,然后此http server也监听了connect的事件,当有method为CONNECT的链接的时候,会触发http server的connect。此时链接打通之后,http server就会创建一个net的链接,去访问需要代理的网站,返回一个serverSocket,然后serverSocket负责读取内容,然后写入clientSocket,clientSocket再告诉serverSocket写入成功,直至代理成功。

webpack的拆包实践(三种方法)

optimization.splitChunks

真拆包,参考链接

module.exports = {//...optimization: {splitChunks: {// ...minChunks: 2,// 这个属性配置了当前模块在不同的模块中出现的次数,如果出现了引用两次的情况,则复用打包出来,这个是真拆包,拆的自己包。// ...}}
};
复制代码

externals剔除不必要的依赖包

只要注意root的问题,root在web下相当于window,因此是window.React,prop-type更不用说了。

externals:{react:{ root: 'React',amd: 'react',commonjs: 'react',commonjs2: 'react' },"prop-types":{ root: 'PropTypes',amd: 'prop-types',commonjs: 'prop-types',commonjs2: 'prop-types' }
}
复制代码

dll和external的区别

exteranl是剔除别人的包。

dll是创建自己的工具库。

const library = '[name]_lib'
module.exports = {mode:"production",entry: {vendors: ['react', 'react-dom']},output: {filename: '[name].dll.js',path: path.join(__dirname,"dist/vendor"),//libraryTarget: "umd",library},plugins: [new webpack.DefinePlugin({ 'process.env': { //用于打包react中的东西NODE_ENV: JSON.stringify("production")} }),new webpack.DllPlugin({path: path.join(__dirname, 'dist/[name]-manifest.json'),// This must match the output.library option abovename: library}),]
}
复制代码

production中使用动态链接库,此处不要配置external。

new webpack.DllReferencePlugin({context: __dirname,manifest: path.join(__dirname, 'dist/vendors-manifest.json'),
})
复制代码

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:cloud.tencent.com/developer/s…

转载于:https://juejin.im/post/5c91e2ca518825284205dcf2

webpack4.0 CheatSheet相关推荐

  1. webpack4.0打包优化策略(二)

    打包优化策略 webpack4.0打包优化策略(一) webpack4.0打包优化策略(二) webpack4.0打包优化策略(三) 区分开发和生产环境 通常我们在开发网页时需要区分构建环境 开发环境 ...

  2. webpack4.0各个击破(2)—— CSS篇

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...

  3. webpack4.0配置记录(2)

    接上一篇webpack4.0配置记录(1),继续记录学习webpack配置. 定义环境变量 new Webpack.DefinePlugin({//用来定义全局环境变量DEV:JSON.stringi ...

  4. 5分钟 学会 webpack4.0之 加薪必备

    点击上方蓝色字,关注置顶 "前端你别闹" 文/北妈 阅读本文需要 3.0分钟 一开始正文之前,先说个八卦放松一下,毕竟周一嘛. 周一本应是良好的开始,但对一个公司仿佛不是那么友好. ...

  5. 前端工具webpack4.0各个击破——html部分

    webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...

  6. 史上最走心的Webpack4.0中级教程——配置之外你应该知道事

    [摘要] <webpack4.0各个击破系列>适合不满足于只会配置webpack但一时间又看不懂源码的中级读者.我没法保证这个系列是最好的,但至少能保证每一篇博文都跟那些Ctrl+C和Ct ...

  7. webpack4.0各个击破(10)—— Integration篇

    [摘要] webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点 ...

  8. webpack4.0各个击破(9)—— karma篇

    [摘要] webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点 ...

  9. webpack4.0各个击破(8)—— tapable篇

    [摘要] webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点 ...

最新文章

  1. 1600802071
  2. 提高ASP性能的最佳选择
  3. Py修行路 python基础 (二十)模块 time模块,random模块,hashlib模块,OS及sys模块...
  4. r怎么对两组数据统计检验_数据科学中最常用的统计检验是什么
  5. python模块用法教程_Python学习之asyncore模块用法实例教程
  6. java 注册页面正则式_Java使用正则表达式对注册页面进行验证功能实现
  7. 源代码可以从应用提取码_大规模下加速源代码分析
  8. 在matlab环境中实现图像的傅里叶变换,matlab用傅里叶变换实现图像的低通滤波
  9. php中几个操作函数参数的函数func_num_args() func_get_args() func_get_arg($i)php
  10. C/C++[codeup 1943](大数)进制转换
  11. vim复制,粘贴,删除,撤销,替换,光标移动等用法
  12. 饮用水配送管理系统项目解决方案
  13. java 定时任务的实现_Java定时任务实现的几种方式
  14. 电脑远程连接已停止工作 解决方案
  15. 在线制作ico矢量图标
  16. 代码之外——禅心慧语
  17. 全网搜索引擎采集(msray)|URL采集|关键词采集|域名采集
  18. mybatis-plus自动填充(创建时间\修改时间)
  19. 孙子兵法 三十六计(猫鼠版)
  20. 亚马逊发多款新品:智能眼镜来了 没摄像头支持语音

热门文章

  1. C++:计算对称正定 (SPD) 矩阵的逆矩阵(附完整源码)
  2. 4x4按键c语言,52单片机C语言4X4键盘.docx
  3. linux驱动设备开发1——字符设备驱动
  4. vue的生命周期函数有哪些
  5. JS获取节点的兄弟,父级,子级元素
  6. Ubuntu安装Samba 服务器
  7. 后端程序员学习前端篇(一)
  8. 微信小程序-人脸识别+输出人脸匹配信息
  9. window下测试ntp服务器是否可用
  10. The Home Depot - 家得宝