使用 webpack 手動搭建 vue 專案

Tuzilow發表於2020-12-07

webpack 是一個前端工程化打包工具,對於前端工程師來說 webpack 是一項十分重要的技能。下面我們就通過搭建一個 vue 專案來學習使用 webpack

主要環境:

  • node v14.15.0
  • npm v6.14.9
  • webpack v5.10.0
  • webpack-cli v4.2.0
  • vue v2.6.12

本專案實現以下功能:

  • vue/cli類似的基本目錄
  • 支援*.vue,*.css等檔案
  • 支援es6及以上語法
  • 支援載入圖片
  • 熱載入

構建專案基本目錄

執行npm init並建立以下目錄

demo
├─ dist
├─ public
└─ src

安裝必要依賴

webpack 及相關外掛

  • webpack npm install -D webpack webpack-cli
  • webpack 本地伺服器外掛 npm install -D webpack-dev-server
  • html 生成外掛,它會將生成的 js 和 css 檔案插入到 html 中 npm install -D html-webpack-plugin
  • vue 外掛 npm install -D vue-loader vue-template-compiler
  • css 外掛 npm install -D css-loader style-loader
  • 圖片外掛 npm install -D file-loader url-loader
  • babel 外掛 npm install -D @babel/core @babel/cli @babel/preset-env babel-loader, npm install @babel/polyfill

安裝 vue

  • npm install vue vue-router

搭建專案

簡單實現 webpack 打包

新建src/main.js,並寫入:

console.log('Hello Webpack');

根目錄下新建webpack.config.js,並寫入:

const path = require('path');

const config = {
  entry: './src/main.js', // 定義入口檔案
  output: {
    path: path.resolve(__dirname + '/dist'), // 打包生成檔案地址,必須是絕對路徑
    filename: '[name].build.js', // 生成的檔名
  },
};
module.exports = config;

package.json中的scripts中新增一個指令碼:

{
  ...
  "scripts": {
    "build": "webpack --mode=production"
  }
  ...
}

在命令列中執行npm run build,此時專案目錄中出現了dist/main.build.js,證明執行成功

js 檔案打包成功後,需要一個 html 檔案來引入這個 js 檔案,這就需要用到我們一開始下載的html-webpack-plugin

首先新建public/index.html建立一個基礎頁面:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>webpack搭建vue</title>
  </head>
  <body>
    <!-- 如果瀏覽器禁止載入js指令碼 -->
    <noscript>
      <strong>
        We're sorry but this site doesn't work properly without JavaScript
        enabled. Please enable it to continue.
      </strong>
    </noscript>

    <div id="app"></div>
    <!-- build後的檔案會在這之後自動引入 -->
  </body>
</html>

public下隨便放入一個圖示favicon.ico,然後在webpack.config.js中配置外掛:

const HtmlWebpackPlugin = require('html-webpack-plugin');

const config = {
  ...
  plugins:[
     new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的資料夾名
      template: 'public/index.html', // 模板html
      favicon: 'public/favicon.ico', // 圖示
    }),
  ]
}
...

之後再次執行npm run builddist下會生成index.htmlfavicon.icomain.build.js三個檔案,通過瀏覽器開啟index.html,就可以發現控制檯輸出了Hello Webpack,頁面圖示也變成了自己設定的圖示,通過編輯器開啟index.html,我們會發現 webpack 幫助我們自動引入了favicon.icomain.build.js

<!DOCTYPE html>
<html>
  <head>
    ...
    <link rel="icon" href="favicon.ico" />
  </head>
  <body>
    ...
    <script src="main.build.js"></script>
  </body>
</html>

開啟熱載入

webpack 熱載入需要用到webpack-dev-server,在開始我們已經安裝過了,在webpack.config.js中配置:

const config = {
  ...
  devServer: {
    contentBase: path.join(__dirname, 'dist'), // html所在路徑
    compress: true, // 是否壓縮
    port: 3000, // 埠
    hot: true, // 熱部署
    open: true, // 打包完成後自動開啟網頁
  }
}

增加package.json指令碼:

{
  ...
  "scripts": {
    "build": "webpack --mode=production",
    "serve": "webpack serve"
  }
  ...
}

執行npm run serve,打包成功後會自動開啟網頁,並且當你修改src/main.jssrc/index.html的內容的時候,瀏覽器會自動重新打包並重新整理

配置 Vue

讓 webpack 打包*.vue檔案需要vue-loadervue-template-compiler,同時為了 webpack 能夠解析 vue 中的 css 還需要用到css-loadervue-style-loader,在webpack.config.js配置以上外掛:

...
const { VueLoaderPlugin } = require('vue-loader');

const config = {
  ...
  // loaders
  module: {
    rules: [
      {
        // *.vue
        test: /\.vue$/,
        loader: 'vue-loader',
      },
      {
        // `*.vue` 檔案中的 `<style>` 塊以及普通的`*.css`
        test: /\.css$/,
        use: ['vue-style-loader', 'css-loader'],
      },
    ],
  },
  plugins: [
    ...
    new VueLoaderPlugin(),
  ],
  ...
};
...

配置完後新建src/App.vue:

<template>
  <div class="example">
    {{ msg }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      msg: 'Hello Webpack',
    };
  },
};
</script>

<style>
.example {
  color: red;
}
</style>

修改src/main.js:

import Vue from 'vue';
import App from './App.vue';

new Vue({
  el: '#app',
  render: (h) => h(App),
});

然後執行npm run serve,即可看到頁面上顯示的Hello Webpack

配置圖片資源的載入

使用file-loaderurl-loader載入,它們都是用於打包檔案和圖片資源的,區別在於url-loader封裝了file-loader

在訪問網站時如果圖片較多,會發很多 http 請求,會降低頁面效能。這個問題可以通過 url-loader 解決。url-loader 會將引入的圖片編碼,生成 dataURl。相當於把圖片資料翻譯成一串字元,再把這串字元打包到檔案中,最終只需要引入這個檔案就能訪問圖片了。
當然,如果圖片較大,編碼會消耗效能。因此 url-loader 提供了一個 limit 引數,小於 limit 位元組的檔案會被轉為 DataURl,大於 limit 的還會使用 file-loader 進行 copy。
此處我們使用 url-loader,由於它是基於 file-loader 的封裝,所以也需要引入 file-loader

...
const config = {
  ...
  module: {
    rules: [
      ...
      {
        // 圖片
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 25000,
          },
        },
      },
    ],
  },
};
...

然後新增一個圖片src/assets/logo.png,在App.vue中引入:

<template>
  <div class="example">
    {{ msg }}
    <img :src="url" />
  </div>
</template>

<script>
import logo from './assets/logo.png';

export default {
  data() {
    return {
      msg: 'Hello Vue1',
      url: logo,
    };
  },
};
</script>

<style>
.example {
  color: red;
}
</style>

再次npm run serve即可看到圖片

配置 babel

babel 可以將 js 的高版本(es6)語法轉換為低版本,使得專案相容低版本瀏覽器

需要我們注意的是,babel7 與 babel6 不相容,因此需要使用最新版本的 babel 和 babel 外掛,在前面文章開始我們已經安裝了 babel7 版本的 babel 外掛,下面我們在webpack.config.js中配置它:

...
const config = {
  ...
  module: {
    rules: [
      ...
      {
        // *.js
        test: /\.js$/,
        exclude: /node_modules/, // 不編譯node_modules下的檔案
        loader: 'babel-loader',
      },
    ],
  },
};
...

配置完後在專案根目錄下建立一個 babel 的配置檔案.babelrc,寫入如下內容:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry"
      }
    ]
  ]
}

更多 babel 配置請檢視babel 中文官網

配置完成後新建一個src/utils/getData.js測試一下:

export default function getData() {
  return new Promise((resolve, reject) => {
    resolve('ok');
  });
}

src/App.vue中引入:

<template>
  <div class="example">
    {{ msg }}
    <img :src="url" />
  </div>
</template>

<script>
import logo from './assets/logo.png';
import getData from './utils/getData';

export default {
  data() {
    return {
      msg: 'Hello Vue1',
      url: logo,
    };
  },
  methods: {
    async fetchData() {
      const data = await getData();
      this.msg = data;
    },
  },
  created() {
    this.fetchData();
  },
};
</script>

<style>
.example {
  color: red;
}
</style>

重新執行npm run serve後,頁面顯示ok,babel 引入成功

設定 src 別名以及省略字尾

為了方便開發,我們可以給 src 目錄設定別名,以及將常用檔案型別的字尾省略

...
const config = {
  ...
  // 解析路徑
  resolve: {
    // 設定src別名
    alias: {
      '@': path.resolve(__dirname, 'src'),
    },
    //字尾名 可以根據需要自由增減
    extensions: ['.js', '.vue'],
  },
  ...
};
...

這樣我們就可以以如下方式匯入 vue 和 js 檔案:

// 匯入App.vue
import App from '@/App';
// 匯入getData
import getData from '@/utils/getData';

至此,我們已經簡單的搭建出了 vue 專案,在專案中我們可能還會需要用到less,sass,字型圖示等工具,針對這類工具 webpack 都有與其對應的loaderplugin,需要時搜尋他們的文件即可。

參考文章

相關文章