因为Webpack以及它的周边工具babel等更新过快,在当前的时间线来看,不少相关的文章已被版本所淘汰,已经不足以借鉴来搭建一个能够正常使用的环境,因此打算写来记录一下。html
在写这篇文章的时候我会同步搭建本地环境,尽可能避免有略过的细节部分。node
熟悉初始化项目的亲可直接跳过。webpack
首先请保证node与npm版本不要过旧,我目前的版本: node v10.15.3 / npm 6.4.1git
建立并进入文件夹my-webpack 并在命令行github
npm init -y
复制代码
而后打开生成的package.json 修改scripts的内容,新增build命令,一下子咱们会用到web
"scripts": {
"build": "webpack"
},
复制代码
安装webpack环境,推荐使用yarn安装,语法与npm差很少,但好处在于安装快,排查错误方便。typescript
yarn add webpack webpack-cli --dev
或
npm install webpack webpack-cli --save-dev
复制代码
安装完成后在当前目录建立webpack.config.js 写入基础配置npm
const path = require('path');
module.exports = {
mode : 'development',//开发环境模式
entry : {
main : './src/index.js'//入口配置
},
output : {
filename : 'bundle.js',//输出配置
path : path.resolve(__dirname, './build')
}
}
复制代码
这时候这个只具有鸡肋功能的webpack环境咱们就搭建好了,接下来咱们将给鸡肋插上 小翅膀 ʚɞjson
此处先不介绍实际代码,由于随着版本迭代,文章中的代码语法等终究会被淘汰,咱们应该学会如何去使用新版本,或者说躲过旧版本语法的坑数组
打开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 文件
// .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还有其余可使用的编译库,英文好的能够直接看官方文档,或者简单了解下配置的其余参数
建立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的编译功能就大功告成了~
同配置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"]
}
复制代码
在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等也均可以一并学会了。