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

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

内容简介:由于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等也都可以一并学会了。


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

查看所有标签

猜你喜欢:

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

SEO深度解析

SEO深度解析

痞子瑞 / 电子工业出版社 / 2014-3-1 / CNY 99.00

《SEO深度解析》以SEO从业人员普遍存在的疑问、经常讨论的问题、容易被忽视的细节以及常见的错误理论为基础,对SEO行业所包含的各方面内容进行了深入的讨论,使读者更加清晰地了解SEO及操作思路。内容分为两类:一类为作者根据自己真实、丰富的SEO经验对SEO所涉及的各种问题进行详细的讨论,主要包括SEO 基础原理剖析、SEO实操思路方法、常用工具数据剖析、竞争对手分析案例实操、网站数据分析思路指导、......一起来看看 《SEO深度解析》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码