因爲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等也均可以一併學會了。