webpack入门二

727 阅读2分钟

续接上篇webpack入门

使用Babel处理ES6

image-20200102195736518

目录结构如上:

如果你在index.js中写了ES6的代码

const arr = [
    new Promise(()=>{}),
    new Promise(()=>{})
]
arr.map(item=>{
    console.log(item)
})

npx webpack打包后,打开打包后的main.js

image-20200102200059402

你会发现,webpack并没有做任何处理,直接将ES6的语法打包了,此时你用谷歌浏览器打开,还是可以正常显示的,因为谷歌浏览器与时俱进,已经支持了ES6,但有些浏览器并不支持ES6。

于是我们希望webpack将ES6的代码转化成ES5的代码,再打包 https://www.babeljs.cn/setup#installationbabel官网对webpack的配置

安装依赖

npm install --save-dev babel-loader @babel/core @babel/preset-env

配置webpack.config.js

module:{
  rules:[
    {
      test:/\.js$/,
      exclude:/node_modules/,// 不用去处理node_modules中的js文件
      loader:'babel-loader',
    }
  ]
}

因为node_modules安装包中,已经帮我们做了语法转换的处理,所以我们不需要再去转换他

npx webpack运行命令后,main.js对ES6的转换如下

image-20200102201441819

可以发现,const被转换成了var,箭头函数被转换成了普通函数,但是Promise并没有被转换

翻译Promise等ES6的新方法

使用@babel/polyfill可以翻译Promise等新的语法 https://www.babeljs.cn/docs/babel-polyfill babel官网

npm install --save @babel/polyfill

index.js文件中引入@babel/polyfill

import "@babel/polyfill"
const arr = [
    new Promise(()=>{}),
    new Promise(()=>{})
]
arr.map(item=>{
    console.log(item)
})

再次运行命令npx webpack

image-20200102203137521

接着你去看main.js比之前多了400多kb,这些是实现Promise等所有高级语法的代码

这时候你会说,那可不可以按需加载,比如只是用到了Promise,那就加载实现Promise的代码就好了

答案是可以的

module:{
  rules:[{
    test:/\.js$/,
    exclude:/node_modules/,
    loader:'babel-loader',
    options:{
      presets:[['@babel/preset-env',{
        useBuiltIns:'usage'
      }]]
    }
  }]
}

npx webpack执行命令后 main.js果然缩小到了60多kb

image-20200102203733772

Babel转化ES6的其他细节

如果我们希望根据浏览器的不同,来决定是不是使用@babel/polyfill

因为有些浏览器已经支持es6就没必要再去转换了

//webpack.config.js
module.exports = {
  module:{
    rules:[
      {
        test:/\.js&/,
        exclude:/node_modules/,
        loader:'babel-loader',
        options:{
          presets:[['@babel/preset-env',{
            targets:{
              edge:"17",
              firefox:"60",
              chrome:"67",
              safari":"11.1"
            },
            useBuiltIns:'usage'
          }]]
        }
      }
    ]
  }
}

npx webpack运行命令后,你会发现main.js缩小到了3.87kb,这大概是因为target中的浏览器版本都支持了promise

image-20200102204404868

以上方案仅适用于普通业务代码,因为对ES6转化为ES5代码是注入到全局的,如果你是开发组件库的话,这样容易造成类名污染

开发组件库的ES6转化为ES5的方案

https://www.babeljs.cn/docs/babel-plugin-transform-runtime babel的官网

npm install --save-dev @babel/plugin-transform-runtime

npm install --save @babel/runtime

npm install --save @babel/runtime-corejs2

module:{
  rules:[{
     test:/\.js$/,
     exclude:/node_modules/,
     loader:'babel-loader',
     options:{
         //presets:[['@babel/preset-env',{
           //  useBuiltIns:'usage',
            // targets:{
            //     edge:"17",
            //     firefox:"60",
            //     chrome:"67",
            //     safari:"11.1"
            // }
         //}]]
        "plugins": [
          [
            "@babel/plugin-transform-runtime",
            {
              // "absoluteRuntime": false,
              "corejs": 2,
              "helpers": true,
              "regenerator": true,
              "useESModules": false
            }
          ]
        ]
    }
  }]
}
//index.js

// import "@babel/polyfill"
const arr = [
    new Promise(()=>{}),
    new Promise(()=>{})
]
arr.map(item=>{
    console.log(item)
})

屏幕快照 2020-01-03 下午5.20.40

当我们配置webpack时。会发现嵌套很多层,我们可以在根目录下新建.babelrc文件,然后将options中的内容复制到.babelrc

// .babelrc

{
    "plugins": [
        [
          "@babel/plugin-transform-runtime",
          {
            // "absoluteRuntime": false,
            "corejs": 2,
            "helpers": true,
            "regenerator": true,
            "useESModules": false
          }
        ]
      ]
}

配置React代码打包

借助babel打包react代码https://www.babeljs.cn/docs/babel-preset-react

mkdir webpack-react

cd webpack-react

npm init -y

npm install webpack webpack-cli -D

安装转化es的依赖

npm install --save-dev babel-loader @babel/core @babel/preset-env

npm install --save @babel/polyfill

 module.exports = {
   module:{
     rules:[
            {
                test:/\.js$/,
                exclude:/node_modules/,
                loader:'babel-loader',
                options:{
                    "presets":[["@babel/preset-env",{
                        targets:{
                            edge:"17",
                            firefox:"60",
                            chrome:"67",
                            safari:"11.1"
                        },
                        useBuiltIns:"usage"
                    }]]
                }
            }
        ]
   }
 }

安装react依赖

npm install react react-dom --save

编写react代码

import "@babel/polyfill"
import React ,{Component} from 'react';
import ReactDom from 'react-dom'
class App extends Component {
  render(){
    return <div>hello world</div>
  }
}
ReactDom.render(<App></App>,document.getElementById('root'))

此时npm run start会报错,因为webpack不能直接打包react我们需要借助babel

npm install --save-dev @babel/preset-react

// webpack.config.js
 rules:[
    {
        test:/\.js$/,
        exclude:/node_modules/,
        loader:'babel-loader',
        options:{
            "presets":[

                ["@babel/preset-env",{//再来转化es6
                	targets:{
                    	edge:"17",
                    	firefox:"60",
                    	chrome:"67",
                    	safari:"11.1"
                	},
                	useBuiltIns:"usage"
            		}],
            	"@babel/preset-react"//先转化react,
        	]
        }
    }
]

注意babel-loader的顺序不能变,必须先转化react, 再去转化ES6

npm run start此时浏览器就可以正常显示react的内容了

结语

如果文章中有错漏处,请看官们指正 如果觉得文章不错的话,请点个赞吧。 作者:胡志武 时间:2020/01/03