webpack架設6 - 圖片與css(scss)打包

這次要來做圖片跟 css 的打包。scss 打包說明在文末,概括來說就是多裝幾個 loader。

本篇文章的 demo code 可以在這邊查看:

webpack架設6 - 圖片與css打包

一樣沿用前面的專案,為了簡單明瞭一點,這次把 router-link 集中放到 header ,移除其他檔案的 router-link。
 

// header.vue

<template>
  <div class="header">
    <router-link to="/">HOME</router-link>
    <router-link to="/cat2">cat2</router-link>
    <router-link to="/cat3">cat3</router-link>
    <router-link to="/catAll">catAll</router-link>
    <p>header</p>
  </div>
</template>

 

// cat1.vue

<template>
   <div style="background: #aabbcc;">
    <p>cat1</p>
  </div>
</template>

 

新增 src/assets/images 資料夾,放入圖片,
然後 cat1, cat2, cat3, catAll 各新增一張圖片。

<img src="../assets/images/cat1.png" alt="cat1.png">

 
順便設定一下 favicon,就是開啟瀏覽器時在頁面名稱旁邊的小 icon,

favicon 可以在 htmlWebpackPlugin 中直接設定:

plugins: [
    new VueLoaderPlugin(),
    new htmlWebpackPlugin({ // 打包HTML
      template: './index.html', // HTML模板路径
      favicon: './src/assets/images/favicon.png'
    })
  ]

 

然後
npm run build
npm run serve
 

打開頁面會發現,嗯,看不到圖片...
這是因為這邊的路徑我寫的是 cat1.vue 相對於 src 圖片資料夾裡 cat1.png 的路徑,
但現在檔案在讀圖片,
需要的是 index.html 相對於 dist 資料夾中圖片的路徑
 

改成

<img src="image/cat1.png" alt="cat1.png">

這樣子就可以正常顯示圖片了。
 

dist 中圖片資料夾的名稱可以在 webpack.config.js 中設定

{
 test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
 loader: 'file-loader',
 options: { name: 'image/[name].[ext]' }
},

路徑會依 options 裡面的配置去打包。

name 圖片原來的名字,預設是 hash
ext 是副檔名
 

接下來可以很開心的,把 cat2.vue, cat3.vue, catAll.vue 都加上圖片,

然後發現!!怎麼只有 cat1 有圖片???

 

看看你的 dist 資料夾裡,竟然!!沒有除了 favicon 跟 cat1.png 之外的其他圖片!

也就是說,你的圖片沒有正確的被打包。

這個部分可以用 import 或 require 的方式引入圖片,

例如

<script>
 require('../assets/images/cat1.png')
</script>

 
一樣
npm run build
npm run serve

這樣,dist 資料夾跟頁面就都看得到圖片了。
 

參考資料

解决vue-cli中webpack无法打包js变量中的图片路径

 

但是如果我需要這個頁面有 100 張圖片,總不能 require 100次吧?
 

不用 require 怎麼做呢?

copy-webpack-plugin

安裝個 plugin: copy-webpack-plugin
這個 plugin 可以幫助我們把圖片整個資料夾打包起來。
 

npm install copy-webpack-plugin --save-dev

 
// webpack.config.js

const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
 plugins: [
  new CopyPlugin([
   { from: './src/assets/images', to: 'image' }
  ])
 ],
};

 

這樣不需要 require,就可以直接把所有指定路徑裡面的圖片打包了。

不過他也會順便幫你打包 favicon,

所以如果你也配置了 htmlWebpackPlugin 的 favicon,

就會 dist 下面有一個 favicon,dist/image 下面也有一個 favicon 了。
 

參考資料

copy-webpack-plugin

 

如果你跟我一樣覺得同時有兩張 favicon 太辣眼睛,可以把 htmlWebpackPlugin 的 favicon 配置取消,

然後直接改 index.html

<head>
 <meta charset="UTF-8">
 <title>webpackDemo</title>
 <link rel="shortcut icon" type="image/png" href="/image/favicon.png"/>
</head>

 
注意這裡的路徑也是要放打包後 dist 資料夾中的路徑

這樣打包出來就不會有兩個 favicon 啦。
 

接下來來把 css 拉出來。

新增 src/assets/style/style.css

.header{background: #55ff55;}
.footer{background: #ffaaff;}
.cat1{background: #aabbcc; }
.cat2{background: #bbccdd; }
.cat3{background: #ccddee; }
.catAll{background: #ddeeff;}

各頁面的行內樣式style換成class

 

ex.
// cat1

<template>
  <div class="cat1">
    <p>cat1</p>
    <img src="image/cat1.png" alt="cat1.png">
  </div>
</template>

 

// index.html 引入 css,這邊的路徑一樣是相對於打包的路徑

<head>
  <meta charset="UTF-8">
  <title>webpackDemo</title>
  <link rel="shortcut icon" type="image/png" href="/image/favicon.png" />
  <link rel="stylesheet" href="css/style.css">
</head>

 

// webpack.config.js 中一樣用 CopyPlugin 做配置

new CopyPlugin([
 { from: './src/assets/images', to: 'image' },
 { from: './src/assets/style', to: 'css' }
])

 
然後一樣
npm run build
npm run serve

 
查看打包檔案

現在我們有css跟image資料夾了,樣式也有正常作用,這樣就算成功啦。
 
 

2020.02.03 更新。

處理 .scss 檔案

前陣子換工作公司主要用 scss,補充一下 scss 打包方式。

 

先來安裝幾個 loader。

npm install sass-loader node-sass -D
npm install css-loader mini-css-extract-plugin -D

 
更新一下設定檔。
// webpack.config.js module.rules

      { test: /\.s[ac]ss$/, 
        loader: [
          "style-loader", 
          "css-loader", 
          'sass-loader'
        ]
      },

 
最後找個檔案來隨便測試一下是否能正常套用樣式,就決定是 header.vue 了。

 
// header.vue

<style lang="scss" scoped>
.header {
  border: solid;
  &:hover {
    background-color: rgb(164, 162, 255);
  }
}  
</style>

 

整理一下頁面,hover 效果正常的話就差不多是沒問題囉。

 

scss 打包參考 code 也丟 github 了,如果小夥伴們發現好像跟上面的 repository 長得不太一樣,不要懷疑,問就是因為我懶得更新舊的XD
 

.scss 檔案全域引用

用 scss 最方便的功能之一就是變數了吧,身為一個喜歡用 css 把網站弄得好像很炫砲的前端,都裝那麼多 loaders 了肯定也要來跟風(?)一下。

 
這裡做個簡單的顏色變數的檔案 _variables.scss,放在 src/assets/style/scss/ 資料夾底下。

// _variables.scss

$mainColor: #ef9595;

 
更新一下設定檔。
// webpack.config.js module.rules

      { test: /\.s[ac]ss$/, 
        loader: [
          "style-loader", 
          "css-loader", 
          'sass-loader', {
            loader: 'sass-resources-loader',
            options: {
              resources: [
                'src/assets/style/scss/*.scss'
              ]
            }
          }
        ]
      },

 
接著一樣拿上面 header.vue 來測試,就把剛剛寫的 background-color 改成 $mainColor

ps. demo 的分支沒有更新全域引用的部分(專案拿去寫作品集 demo 了,還沒改完,整體進度可以直接點最新 commit 查看)。

background-color: $mainColor;

如果顏色一樣有吃到,就表示引用成功,可以下班囉~

 

參考資料

Webpack 前端打包工具 - 使用 sass-loader 編譯 Sass/SCSS 預處理器

How to export a global scss variables file to be imported to all scss files in Rails 6 webpacker