配置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,第一个结果就是了,打开后向下滚动查看它的介绍:
它已经清楚的介绍了此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的配置经常随着时间变化而改变,希望能避免配置新版本环境时不必要的踩坑 ~
而要写全所有功能的配置需要大量的时间,暂且没有精力,所以目前先写这种虽然精简却能用到的功能。
只要学会如何自己去找到配置babel-loader的方法,配置其他CSS-loader等也都可以一并学会了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 介绍同步加载、异步加载、延迟加载[原创]
- 基于echarts异步加载数据之多个series加载实例
- 使WPF图像加载异步
- CSS 异步加载技术 不影响页面渲染
- Vue异步组件处理路由组件加载状态
- 简单的算法-解决页面脚本异步加载顺序问题
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。