Webpack学习

141 阅读5分钟

2020.11.28

浏览器请求各种静态资源 脚本is slow,得想办法把这些整合起来,

而使用es6模块化的require引入资源,浏览器不支持 浏览器端的模块系统无法使用,不只是require了,即使是es6标准的import很多低版本的浏览器也无法支持,尤其是IE,目前并没有很好的解决方案使得浏览器端自然的使用各个模块系统,只能使用webpack等工具预先将所有的依赖打包,最终在浏览器换进中运行

npm init -y
npm install webpack webpack-cli -D

1.新建 src/index.js 文件

npx webpack或者npx webpack --mode=development 进行构建,默认是 production 模式,我们为了更清楚得查看打包后的代码,使用 development 模式

使用 babel-loader,将打包的JS代码向低版本转换

npm install babel-loader -D
npm install @babel/core @babel/preset-env @babel/plugin-transform-runtime -D

npm install @babel/runtime @babel/runtime-corejs3

2.新建 webpack.config.js

   module.exports = {
     module: {
        rules: [
            {
                test: /\.jsx?$/,
                use: ['babel-loader'],
                exclude: /node_modules/ //排除 node_modules 目录
            }
        ]
    }
}

新建 .babelrc 配置**babel**,也可以在 webpack.config.js 中进行配置

{  "presets": ["@babel/preset-env"],  "plugins": [      [          "@babel/plugin-transform-runtime",          {              "corejs": 3          }      ]  ]}

运行npx webpack --mode=development 看效果,打包的代码变多了,看不懂~

npm install html-webpack-plugin -D
注:指定打包文件中带有 hash,那么每次生成的 js 文件名会有所不同,不用每次手动去修改HTML)
npm install cross-env -D 兼容Windows与mac
npm install webpack-dev-server -D 在浏览器中实时查看效果,版本有问题,使用webpack serve

3.处理css

webpack借助loader处理css

我们需要的 loader 通常有: style-loadercss-loader,考虑到兼容性问题,还需要 postcss-loader,而如果是 less 或者是 sass 的话,还需要 less-loadersass-loader

npm install style-loader less-loader css-loader postcss-loader autoprefixer less -D
style-loader 动态创建 style 标签,将 css 插入到 head 中.css-loader 负责处理 @import 等语句。postcss-loader 和 autoprefixer,自动生成浏览器兼容性前缀 —— 2020了,应该没人去自己徒手去写浏览器前缀了吧less-loader 负责处理编译 .less 文件,将其转为 css

4.图片/字体文件处理

npm install url-loader -D
npm install file-loader -D
有警告信息还得安装precss cssnano

奇怪:require 有的图片生效有的不生效???------需要重新构建。。npm run dev是仅仅运行,npx webpack 重新打包,或者是npm run build----再跑

5.入口与出口配置

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'), //必须是绝对路径
        filename: 'bundle.[hash].js',
        publicPath: '/' //通常是CDN地址
    }
}

由于每次文件修改后,重新打包,导致 dist 目录下的文件越来越多
npm install clean-webpack-plugin -D 帮助打包前清空目录

//webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
    //...
    plugins: [
        //也可以不传参数,它可以找到 outputPath
        new CleanWebpackPlugin({
            cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] //不删除dll目录下的文件
        }) 
    ]
}

6.按需加载

不同阶段去加载所需要的代码 , 使用 import(***),会生成一些chunk

webpack 遇到 import(****) 这样的语法的时候,会这样处理:以**** 为入口新生成一个 Chunk

7.打包清空dist

npm install clean-webpack-plugin -D
//webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    //...
    plugins: [
        //不需要传参数喔,它可以找到 outputPath
        new CleanWebpackPlugin() 
    ]
}

8.webpack解决跨域问题

新建server.js模拟接口,使用到express

let express = require('express');
let app = express();app.get('/user', (req, res) => {    
    res.json({name: '周星星'});});app.listen(4000);
    // node server.js 浏览器输入即可http://localhost:4000/api/user

在入口文件请求接口

fetch("/api/user")    .then(response => response.json())    .then(data => console.log(data))    .catch(err => console.log(err));

webpack修改配置

 devServer: {        
    port: '3000', //默认是8080        
    // 实现跨域        
    proxy: {            
        // "/api": "http://localhost:4000"            
        '/api': { // server.js去前缀写法                
        target: 'http://localhost:4000',                
        pathRewrite: {                    
        '/api': ''                
        }     
      }        
    }    
},

参考:juejin.cn/post/684490…

9.构建流程

初始化配置参数 -> 加载plugin,实例化compiler -> 确定Entry逐一遍历 -> 调用loader去加载模块 -> 输出文件

10. 优化

gzip文件压缩( Nginx 开启 gzip,服务端压缩浏览区解压)、CDN(减少Webpack打包出来的js体积)、图片压缩、去除sourceMap

devServer: {    port: 8080,    proxy: 'http://192.168.0.249/',  },
// 表示当前项目启动端口为8080,即localhost:8080
在开发阶段, webpack-dev-server 会启动一个本地开发服务器,运行在localhost:8080
所以我们的应用在开发阶段是独立运行在 localhost的一个端口上,而后端服务又是运行在另外一个地址上http://192.168.0.249/
当本地发送请求的时候,代理服务器响应该请求,并将请求转发到目标服务器,目标服务器响应数据后再将数据返回给代理服务器,最终再由代理服务器将数据响应给本地
通过设置webpack proxy实现代理请求后,相当于浏览器与服务端中添加一个代理者
!!!服务器与服务器之间请求数据并不会存在跨域行为,跨域行为是浏览器安全策略限制

Q1:webpack没有配置跨域 竟然没报错是什么原因?---使用的CORS,只需要后端配置access-control-allow-origin:*,浏览器在发送请求时,检测到跨域时,会自动加上一个额外的 Origin 头部,前端不用做任何操作即可访问
Q2:配置pathrewrite??---通常是因为API对应了多个服务器域名,用作区分匹配,匹配完之后再改回来,如果没有做区分可以不加pathrewrite
Q3: get请求—带#号是什么意思??—获取到资源文件
Q4:'/api': 'http://localhost:3000'表示----'/api',表示如果API中有这个字符串,会被代理到请求 http://localhost:3000/api/xxx,target表示需要跨域的地址,设置target后,devserver会弄一个代理服务器去模拟浏览器发送请求。如果target是个域名,需要设置changeOrigin:true,否则会代理失败;如果要设置支持https协议,设置secure:false,不检查安全问题 axios: url:'/assess/xxx',baseUrl:'/api',baseUrl自动加在url前面除非url是个绝对URL,假设你vue-cli起了一个开发环境,地址为http://localhost:8080,那么最终请求地址就是http://localhost:8080/api/assess/xxx