前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >webpack4.0 CheatSheet

webpack4.0 CheatSheet

作者头像
小美娜娜
发布于 2019-04-04 07:00:32
发布于 2019-04-04 07:00:32
88300
代码可运行
举报
文章被收录于专栏:小美娜娜小美娜娜
运行总次数:0
代码可运行

还在为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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npx babel src --out-dir lib
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev @babel/preset-react
npm install --save-dev react react-dom
复制代码
TS全配置
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev typescript
复制代码

ts可以用babel编译

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev @babel/preset-typescript
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev ts-loader
复制代码

有关CSS加载的一些见解

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

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 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自带的服务器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev webpack-dev-server
复制代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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自带的服务器的跨域问题

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

自定义服务器

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev express webpack-hot-middleware webpack-dev-middleware
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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一致。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
app.use(require("webpack-hot-middleware")(compiler,{
  log: false,
  path: "/__what",
  heartbeat: 2000
}));
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if(module.hot){
  module.hot.accept()
}
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
npm install --save-dev http-proxy-middleware
复制代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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…

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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并不是什么难事。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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这个方法,链接到了请求链接,建立了互读互写的管道。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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_connect
        path: '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 tunnel
        socket.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

真拆包,参考链接

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

externals剔除不必要的依赖包

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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是创建自己的工具库。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 above
      name: library
    }),
  ]
}
复制代码

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
new webpack.DllReferencePlugin({
    context: __dirname,
    manifest: path.join(__dirname, 'dist/vendors-manifest.json'),
})
复制代码
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年03月21日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
C# 多线程编程入门教程
随着硬件性能的提升,尤其是多核CPU的广泛应用,多线程编程已经成为现代软件开发中的核心技能之一。多线程可以让程序在多个核心上并发运行,提高效率和性能。然而,编写多线程程序并不是一件简单的事情,尤其是要处理线程间的同步问题,以避免数据竞争和死锁等问题。
Michel_Rolle
2024/09/23
2.9K0
C# 异步编程与多线程简析:Thread、ThreadPool、Task
C# 提供了多种机制来支持异步编程和多线程,其中Thread、ThreadPool 和Task 是最为常用的三种。
软件架构师Michael
2024/12/24
3580
C# 中的线程与任务 — 有什么区别?
在C#编程中,类(class)是一种让我们可以同时执行任务的方式,允许我们在程序的其他部分继续运行时执行代码。尽管现代C#开发人员通常使用Task来管理并发性,但Thread类提供了更多的线程行为控制,这使得它在需要进行低级别线程操作时非常有用。
郑子铭
2025/01/07
3030
C# 中的线程与任务 — 有什么区别?
C#多线程编程_wpf和winform的区别
线程 被定义为程序的执行路径。每个线程都定义了一个独特的控制流。在多线程之下可以通过分配线程,同时处理多个任务。
全栈程序员站长
2022/11/01
5200
C#的线程池
在多线程编程中,频繁地创建和销毁线程会带来巨大的性能开销。为了解决这个问题,.NET Framework引入了线程池(ThreadPool),它是一个用于管理线程生命周期的机制,可以有效地重用线程,减少资源消耗,并提高程序的响应速度。本文将深入探讨C#中线程池的工作原理、使用场景、最佳实践以及一些高级技巧。
Michel_Rolle
2024/10/09
2.9K0
【深入浅出C#】章节 9: C#高级主题:多线程编程和并发处理
多线程编程和并发处理的重要性和背景 在计算机科学领域,多线程编程和并发处理是一种关键技术,旨在充分利用现代计算机系统中的多核处理器和多任务能力。随着计算机硬件的发展,单一的中央处理单元(CPU)已经不再是主流,取而代之的是多核处理器,这使得同时执行多个任务成为可能。多线程编程允许开发人员将一个程序拆分成多个线程,这些线程可以并行执行,从而提高程序的性能和响应速度。 为什么多线程在现代应用中至关重要?
喵叔
2023/08/26
5.2K0
VB.NET中,多线程的学习笔记(一)
在VB.NET中,System.Threading 命名空间提供了多种与线程相关的类和接口。其中 Thread 类是用于创建和管理线程的主要类,以下是一些主要的属性和方法:
哆哆Excel
2024/02/26
8550
多线程编程01
线程可以被描述为它所处的进程中的一个微进程,它拥有起点,执行的顺序系列和一个终点。
Echo_Wish
2023/11/30
1870
C#多线程之旅(3)——线程池
v博客前言 先交代下背景,写《C#多线程之旅》这个系列文章主要是因为以下几个原因:1.多线程在C/S和B/S架构中用得是非常多的;2.而且多线程的使用是非常复杂的,如果没有用好,容易造成很多问题。
悟空聊架构
2018/05/18
1.1K0
.NET中的异步编程上
开篇 异步编程是程序设计的重点也是难点,还记得在刚开始接触.net的时候,看的是一本c#的Winform实例教程,上面大部分都是教我们如何使用Winform的控件以及操作数据库的实例,那时候做的基本都是数据库的demo,数据量也不大,程序在执行的时候基本上不会出现阻塞的情况。随着不断的深入.net,也开始进入的实战,在实际的项目,数据量往往都是比较大,特别是在大量的数据入库以及查询数据并进行计算的时候,程序的UI界面往往卡死在那里,发生了阻塞,这时候就需要对计算时间限制的过程进行异步处理,让UI线程继续相应
逸鹏
2018/04/10
1.3K0
.NET中的异步编程上
Java线程池详解
  当任务数量上升到1000+,这样内存开销太大,我们希望有固定数量的线程,来执行这1000个线程,这样就避免了反复创建并销毁线程所带来的开销问题。
砖业洋__
2023/05/06
4100
Java线程池详解
C#多线程开发-线程池03
前面2篇文章介绍了线程的基础知识和线程同步,下面我们来一起认识学习下,线程池的使用。
zls365
2021/09/24
9640
C#多线程开发-线程池03
【Python基础编程】深入掌握线程与线程池的高效应用
上篇文章讲述的是python的异常处理和文件读写,这篇文章讲述python的并发编程:线程。
易辰君
2024/11/07
1370
【Python基础编程】深入掌握线程与线程池的高效应用
用CompletableFuture,品怨种码生,写线上BUG,拿C+绩效
Hey小伙伴们,今天要给大家安利一篇操作实践的文章,相信大家通过仔细阅读,一定会有所收货!
不惑
2024/12/03
5782
用CompletableFuture,品怨种码生,写线上BUG,拿C+绩效
.NET基础拾遗(5)多线程开发基础
  下面的一些基本概念可能和.NET的联系并不大,但对于掌握.NET中的多线程开发来说却十分重要。我们在开始尝试多线程开发前,应该对这些基础知识有所掌握,并且能够在操作系统层面理解多线程的运行方式。
Edison Zhou
2018/08/20
8780
.NET基础拾遗(5)多线程开发基础
C#线程
线程 ----   线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,即不同的线程可以执行同样的函数。   多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。   多线程可以提高CPU的利用率。在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,这样就大大提高了程序的效率。   在 C# 中,System.Threading.Thread
拾点阳光
2018/05/10
9120
.NET Core多线程 (1) Thread与Task
.NET Core中加入了本地队列,加入了本地队列,降低了锁竞争,并提高了线程的利用率。
Edison Zhou
2023/08/09
6230
.NET Core多线程 (1) Thread与Task
C#基础知识学习之 ☀️ | 多线程的使用基础
线程在程序中经常被用到,现在的计算机都是可以异步执行很多操作的,所以多线程的作用可见一斑!
呆呆敲代码的小Y
2021/10/29
8260
C#基础知识学习之 ☀️ | 多线程的使用基础
C#线程入门
 C#支持通过多线程并行地执行代码,一个线程有它独立的执行路径,能够与其它的线程同时地运行。一个C#程序开始于一个单线程,这个单线程是被CLR和操作系统(也称为“主线程”)自动创建的,并具有多线程创建额外的线程。
aehyok
2018/09/11
5480
C#线程入门
.Net异步编程知多少
1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法。异步编程说起来,大家可能都会说异步编程性能好。但好在哪里,引入了什么问题,以及如何使用,想必也未必能答的上来。
圣杰
2018/01/11
9230
.Net异步编程知多少
相关推荐
C# 多线程编程入门教程
更多 >
LV.1
a实时计算
目录
  • Loaders全配置
  • babel配置
    • @babel/preset-env
    • @babel/polyfill
    • 其他plugin
      • REACT全配置
      • TS全配置
  • 有关CSS加载的一些见解
  • HMR热更新配置——减少手动编译刷新页面
    • webpack自带的服务器
    • webpack自带的服务器的跨域问题
    • 自定义服务器
    • http-proxy-middleware——解决开发中的跨域问题
  • 压箱底的proxy研究
    • 基于第三方插件的proxy配置开发
    • 手动写一个
  • webpack的拆包实践(三种方法)
    • optimization.splitChunks
    • externals剔除不必要的依赖包
    • dll和external的区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档