配置Webpack4支持ES6/TypeScript/异步文件引用加载

栏目: JavaScript · 发布时间: 6年前

内容简介:由于Webpack以及它的周边工具babel等更新过快,在当前的时间线来看,很多相关的文章已被版本所淘汰,已经不足以借鉴来搭建一个可以正常使用的环境,所以打算写来记录一下。在写这篇文章的时候我会同步搭建本地环境,尽量避免有略过的细节部分。熟悉初始化项目的亲可直接跳过。

由于Webpack以及它的周边工具babel等更新过快,在当前的时间线来看,很多相关的文章已被版本所淘汰,已经不足以借鉴来搭建一个可以正常使用的环境,所以打算写来记录一下。

在写这篇文章的时候我会同步搭建本地环境,尽量避免有略过的细节部分。

环境起步

熟悉初始化项目的亲可直接跳过。

首先请保证node与npm版本不要过旧,我目前的版本: node v10.15.3 / npm 6.4.1

创建并进入文件夹my-webpack 并在命令行

npm init -y 
复制代码

然后打开生成的package.json 修改scripts的内容,新增build命令,一会儿我们会用到

"scripts": {
    "build": "webpack"
},
复制代码

安装webpack环境,推荐使用yarn安装,语法与npm差不多,但好处在于安装快,排查错误方便。

yarn add webpack webpack-cli --dev
或
npm install webpack webpack-cli --save-dev
复制代码

安装完成后在当前目录创建webpack.config.js 写入基础配置

const path = require('path');

module.exports = {
    mode : 'development',//开发环境模式
    entry : {
        main : './src/index.js'//入口配置
    },
    output : {
        filename : 'bundle.js',//输出配置
        path : path.resolve(__dirname, './build')
    }
}
复制代码

这时候这个只具备鸡肋功能的webpack环境我们就搭建好了,接下来我们将给鸡肋插上 小翅膀 ʚɞ

配置编译ES6的Loader

此处先不介绍实际代码,因为随着版本迭代,文章中的代码语法等终究会被淘汰,我们应该学会如何去使用新版本,或者说躲过旧版本语法的坑

打开github搜索babel-loader,第一个结果就是了,打开后向下滚动查看它的介绍:

配置Webpack4支持ES6/TypeScript/异步文件引用加载

它已经清楚的介绍了此loader的支持环境 需要webpack 4作为基础环境支持

我们按照它的介绍安装loader,由于webpack刚才我们已经安装过了,此处可以去掉,但我们需要做浏览器兼容,在命令行中多加入一个 @babel/polyfill的扩展 如下↓

yarn add babel-loader @babel/core @babel/preset-env @babel/polyfill --dev
复制代码

安装完成后我们开始修改webpack.config.js

让其支持Loader的编译,此处你不需要记得清楚loader如何配置,在刚才babel-loader介绍安装方式的下方有教你如何配置,直接拿来粘贴即可:

entry..
output...
//重复代码略过 同级写入
module : {
    rules : [
        {
            test: /\.js$/,
            exclude: /(node_modules)/,
            use: {
                loader: 'babel-loader'
            }
        }
    ]
}
复制代码

实际使用webpack.config.js的配置项非常之多,babel-loader的options也有很多需要配置的,此处我们已经删掉了loader中options这个键值,在当前目录下新建 .bebelrc 文件

配置它的options:

// .babelrc
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "browsers": ["> 1%","last 2 versions","Android >= 3.2", "Firefox >= 20","iOS 7"]
                },
                "corejs":2,
                "useBuiltIns": "usage"
            }
        ]
    ]
}
复制代码

配置参数的介绍

  • @babel/preset-env : 是babel编译的基础库,它下个对象中的参数,是针对于它默认配置的重定义 ↓
  • targets :即在编译时根据我们的需求写入浏览器版本进行兼容
  • useBuiltIns :默认值为false,它很重要,我们此处改为"usage",即为按需引入:是否只编译你脚本中使用过的API,如Promise,如果为false则不会使用polyfill进行编译
  • corejs :配合useBuiltIns使用,告诉它编译时使用哪儿个core-js的版本作为核心库进行编译,如果不声明也可以正常运行,但是命令行会有警告提示说这样做是有隐患的,所以我们在此处声名大版本为 2 即可,那么如何查看我们corejs的大版本呢,它又是什么时候安装的呢?其实在安装@babel/polyfill的时候就已经被自动安装上了,我们只需要找到扩展node_moudules/@babel/polyfill 查看它package.json中记录的文件依赖,它里面会清楚写着core-js的版本号,而corejs我们也可以手动安装,但默认版本corejs已经是3起步了,所以通过@babel/polyfill默认安装即可

除了@babel/preset-env还有其他可以使用的编译库,英文好的可以直接看官方文档,或者简单了解下配置的其他参数

编译代码看效果

创建src文件夹,并新建index.js 我们试一试Promise与ES6语法能否在IE下正常运行

//index.js
const imgPromise = (imgSrc) => {
    return new Promise((resolve, reject)=>{
        const img = new Image();
        img.onload = () =>{
            resolve(img);
        }
        img.onerror = () => {
            reject();
        }
        img.src = imgSrc;
    });
}
const newImgSrc = 'http://b.hiphotos.baidu.com/image/h%3D300/sign=77d1cd475d43fbf2da2ca023807fca1e/9825bc315c6034a8ef5250cec5134954082376c9.jpg';
const newImg = new imgPromise(newImgSrc).then((img)=>{
    document.body.appendChild(img);
},()=>{
    console.log("img error");
});
复制代码

编译输出它,即在目录中生成build文件夹与bundle.js文件 ↓

npm run build

在build文件夹中创建index.html,引入bundle.js

(html文件可以通过配置webpack的HtmlWebpackPlugin来自动生成,此处手动创建,只为看到编译效果)

然后使用IE打开index.html文件即可看到图片加载,到这里,我们ES6语法 & API的编译功能就大功告成了~

支持TypeScript

同配置babel-loader的方法一样,直接去github搜索编译TypeScript的 ts-loader 安装它

yarn add ts-loader typescript --dev
复制代码

在webpack配置文件的rules数组中增加ts-loader

//webpack.config.json

rules:[
    ...babel-loader,
    { 
        test: /\.tsx?$/,
        exclude: /(node_modules)/,
        loader: "ts-loader"
    }
]
复制代码

同理,在项目根目录新增一个 tsconfig.json 配置ts-loader

//tsconfig.json
{
    "compilerOptions": {
        "module": "UMD",
        "target": "es5",
        "sourceMap": true,
        "allowJs": true
    },
    "exclude": ["node_modules", "dist", "build", "mock"]
}
复制代码
  • module :模块的引入方式
  • target :编译后的运行环境
  • allowJs :允许编译JS文件
  • 更多配置介绍中文 /英文

开始编译TypeScript

在src目录创建一个TS文件

//test.ts
interface Person {
    firstName: string;
    lastName: string;
}

function greeter(person: Person) {
    return "Hello, " + person.firstName + " " + person.lastName;
}

export default greeter;
复制代码

然后通过import形式引入它

//index.js
import greeter from './test.ts'

...省略之前测试Promise的代码


let user = { firstName: "Jane", lastName: "User" };
console.log(greeter(user));
复制代码

执行编译后我们可直接打开build/index.html文件,打开控制台查看console

即可看到TS文件被成功编译,IE11也可正常使用,还可以在控制台看到它编译后的代码:

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (factory) {
    if ( true && typeof module.exports === "object") {
        var v = factory(__webpack_require__("./src sync recursive"), exports);
        if (v !== undefined) module.exports = v;
    }
    else if (true) {
        !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__, exports], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
				__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
				(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
				__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
    }
})(function (require, exports) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    function greeter(person) {
        return "Hello, " + person.firstName + " " + person.lastName;
    }
    exports.default = greeter;
});
复制代码

脚本异步引用加载

本文的最后一个环节,也是开发中会经常用到的功能

如果一次加载大量的文件,或有些代码并不需要在页面初次进来的时候进行加载,可以很好地优化项目的加载速度。

在output中新增chunkFilename 意为分割后文件的命名规则

//webpack.config.js
output:{
    ...,
    chunkFilename: '[name].bundle.js'
}
复制代码

安装@babel/plugin-syntax-dynamic-import并扩展babel-loader配置,使其支持动态文件引入

yarn add @babel/plugin-syntax-dynamic-import --dev

//扩展.babelrc 新增plugins参数
{
    "presets": [
        [
            "@babel/preset-env",
            {
                "targets": {
                    "browsers": ["> 1%","last 2 versions","Android >= 3.2", "Firefox >= 20","iOS 7"]
                },
                "corejs":2,
                "useBuiltIns": "usage"
            }
        ]
    ],
    "plugins": ["@babel/plugin-syntax-dynamic-import"]
}
复制代码

通过import动态引入文件 webpackChunkName注释的值test 会在 chunkFilename的[name]中使用

//index.js增加以下代码 
function getTest(obj){
    return import(/* webpackChunkName: "test" */ './test.ts').then(({default:test})=>{
        console.log(test(obj));
    }).catch(error=>{
        console.log(error);
    })
}
//或者使用async/await来处理异步插件 
async function getTest(obj){
    await import(/* webpackChunkName: "test" */ './test.ts').then(({default:test})=>{
        console.log(test(obj));
    }).catch(error=>{
        console.log(error);
    })
}

document.body.onclick = () =>{
    let user = { firstName: "Jane", lastName: "User" };
    getTest(user);
}
复制代码

此时命令行运行

npm run build

输出文件

bundle.js  91.5 KiB

test.bundle.js  1.95 KiB
复制代码

此时我们可以打开index.html 开启F12看到页面只加载了bundle.js

当你点击了图片时会动态加在test.bundle.js,并在命令行中输出

Hello, Jane User

简单的代码分割与动态加载就实现了,但实际业务中存在很多公用的脚本,不能将所有的代码都进行分割

而我这里只写了异步加载的代码分割,还有同步代码的分割可进行设置,有很多参数需要配置,需要耐心的了解

webpack-splitChunks

尾儿

webpack的配置经常随着时间变化而改变,希望能避免配置新版本环境时不必要的踩坑 ~

而要写全所有功能的配置需要大量的时间,暂且没有精力,所以目前先写这种虽然精简却能用到的功能。

只要学会如何自己去找到配置babel-loader的方法,配置其他CSS-loader等也都可以一并学会了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Compilers

Compilers

Alfred V. Aho、Monica S. Lam、Ravi Sethi、Jeffrey D. Ullman / Addison Wesley / 2006-9-10 / USD 186.80

This book provides the foundation for understanding the theory and pracitce of compilers. Revised and updated, it reflects the current state of compilation. Every chapter has been completely revised ......一起来看看 《Compilers》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器