webpack加載不一樣的資源

本文內容以下:

1 加載單一JS文件
2 加載2個或多個js
3 引入JSON文件
4 加載字體
5 加載數據CSV/TSV/XML
6 加載CSS文件介紹
7 實際操做:
8 單獨打包CSS,ExtractTextWebpackPlugin插件
9 CSS modules
10 CSS預處理器
11 加載Sass
12 在 Webpack 中使用公用 CDN
13 當第三方庫,不支持CommonJS或AMD時。或者須要前置庫時。
13.1 使用webpack.ProvidePlugin
13.2 使用imports-loader


加載單一JS文件

以lodash.js爲例子javascript

安裝lodashcss

npm i lodash --save-dev複製代碼

//index.jshtml

import _ from 'lodash';
function component () {
  var element = document.createElement('div');
  /* 須要引入 lodash,下一行才能正常工做 */
  element.innerHTML = _.join(['Hello','webpack'], ' ');
  return element;
}
document.body.appendChild(component());複製代碼

而後運行webpack。便可。java

加載2個或多個js

若是是本身寫的代碼,經過require("./book.js");引入便可。node

若是是第三方庫,先安裝,再經過require()或import引入便可。react

引入JSON文件

zyx456:JSON文件能夠直接用require(filename)引入使用。jquery

var config = require('./test.json');
 import Data from './data.json'複製代碼

相似於 NodeJS,JSON 支持其實是內置的,也就是說將正常運行。webpack

項目目錄:git

JS/github

  • config.json
  • entry.js

//test.json文件

{
  "greetText": "Hi there and greetings from JSON!"
}複製代碼

entry.js

var config = require('./test.json');
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};複製代碼

加載字體

file-loader 和 url-loader 能夠接收並加載任何文件,而後將其輸出到構建目錄。

這就是說,咱們能夠將它們用於任何類型的文件,包括字體。

webpack.config.js

const path = require('path');
  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
       {
         test: /\.(woff|woff2|eot|ttf|otf)$/,
         use: [           'file-loader'         ]
       }
      ]
    }
  };複製代碼

在項目中添加一些字體文件:

project

webpack-demo  
|- package.json  
|- webpack.config.js 
|- /dist    
|- bundle.js    
|- index.html  
|- /src+   
|- my-font.woff+  
|- my-font.woff2
|- icon.png
|- style.css
|- index.js
|- /node_modules複製代碼

配置加載器並使用字體後,可使用@font-face聲明來合併它們。

webpack將獲取本地url(...)指令,就像使用圖像同樣:

src/style.css

+ @font-face {
+   font-family: 'MyFont';
+   src:  url('./my-font.woff2') format('woff2'),
+         url('./my-font.woff') format('woff');
+   font-weight: 600;
+   font-style: normal;
  }
  .hello {
    color: red;
   font-family: 'MyFont';
    background: url('./icon.png');
  }複製代碼

加載數據CSV/TSV/XML

能夠加載的有用資源還有數據,如 CSV、TSV 和 XML。

可使用 csv-loaderxml-loader

npm install --save-dev csv-loader xml-loader複製代碼

webpack.config.js

const path = require('path');
  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.(csv|tsv)$/,
+         use: [
+           'csv-loader'
+         ]
+       },
+       {
+         test: /\.xml$/,
+         use: [
+           'xml-loader'
+         ]
+       }
      ]
    }
  };複製代碼

project

webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- data.xml
    |- my-font.woff
    |- my-font.woff2
    |- icon.png
    |- style.css
    |- index.js
  |- /node_modules複製代碼

src/data.xml

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Mary</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Call Cindy on Tuesday</body>
</note>複製代碼

如今,你能夠 import 這四種類型的數據(JSON, CSV, TSV, XML)中的任何一種,所導入的 Data 變量將包含可直接使用的已解析 JSON:

src/index.js

import _ from 'lodash';
  import './style.css';
  import Icon from './icon.png';
+ import Data from './data.xml';
  function component() {
    var element = document.createElement('div');
    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');
    // Add the image to our existing div.
    var myIcon = new Image();
    myIcon.src = Icon;
    element.appendChild(myIcon);
+   console.log(Data);
    return element;
  }
  document.body.appendChild(component());複製代碼

加載CSS文件介紹

若是直接在index.js文件裏引入 CSS:

import styles from './assets/stylesheets/application.css';複製代碼

會遇到如下的錯誤:You may need an appropriate loader to handle this file type。

在應用中添加 css 文件,就須要使用到 css-loader 和 style-loader。

css-loader 會遍歷 CSS 文件,而後找到 url() 表達式而後處理他們。可以使用相似@import 和 url(...)的方法實現 require()的功能。

style-loader 會把原來的 CSS 代碼插入頁面中的一個 style 標籤中。

在編譯時,css-loader會讀取CSS文件,並處理其中的import,返回CSS代碼;

而style-loader會將返回的CSS代碼做爲DOM的style。

在生產構建下,CSS 是會被打包到 JavaScript 裏的,style-loader 會把你的樣式寫在 Style 標籤裏。

css-loader用來返回有@import和url()的css文件style-loader用來將css文件插入頁面。

能夠根據需求將一些圖片自動轉成base64編碼的,減輕不少的網絡請求。


實際操做:

安裝 css-loader 和 style-loader(全局安裝須要參數 -g)。

cnpm install css-loader style-loader複製代碼

安裝url-loader

npm install url-loader --save-dev複製代碼

而後給 webpack.config.js 添加一條規則:

Loaders會根據數組的逆序運行,也就是說 css-loader會跑在 style-loader 前面。

module.exports = {
  // …
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      // …
    ],
  },
};複製代碼


webpack 根據正則表達式,來肯定應該查找哪些文件,並將其提供給指定的 loader。在這種狀況下,以 .css 結尾的所有文件,都將被提供給 style-loader 和 css-loader。

添加css文件,注意文件的路徑。

js/style.css

body {background: yellow; }複製代碼

在JS文件引入CSS文件。

import './style.css'複製代碼

如何css文件根目錄/css/a.css

那麼

import '../css/a.css';複製代碼

css會和js打包到同一個文件中。

實際網頁中,含有 CSS 字符串的 <style> 標籤,將被插入到 html 文件的 <head> 中。

單獨打包CSS,ExtractTextWebpackPlugin插件

單獨打包CSS,把 CSS 從 js 文件當中獨立出來。

若是把CSS打包到JS中,有一個性能上的問題,就是沒法使用瀏覽器去異步並並行地加載CSS。

反而,你的文件須要等待整個JavaScript文件加載完,才能進行渲染。

在咱們的網頁設計中,有一種平穩退化的概念。就是說,HTML是最重要的,其次是CSS,最後是JavaScript。

官方文檔是以插件的形式作的:

webpack.github.io/docs/styles…

注意一下函數參數,第一第二個參數是有區別的,好比這樣用:

第一個參數是編譯好之後的代碼用的,第二個參數是編譯到源代碼用的。

ExtractTextPlugin.extract('style-loader''css!less')複製代碼

對插件進行開發依賴安裝

$ npm install --save-dev extract-text-webpack-plugin複製代碼

而後,咱們須要修改咱們的webpack.config.js配置文件:

//webpack.config.js
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
  entry: './app/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
        rules: [{
            test: /\.css$/,
            //use: [ 'style-loader', 'css-loader' ]
            use: ExtractTextPlugin.extract({
              use: 'css-loader'
            })
        }]
    },
    //ExtractTextPlugin
    plugins: [
      new ExtractTextPlugin('styles.css'),
    ],
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    inline: true
    }
};複製代碼

這樣的設置下,webpack會在dist文件夾中生成一個彙總的styles.css文件。

你須要將它做爲一個單獨的樣式加入到index.html中。在HTML文件中手動引入.css文件。

CSS modules

最近有一個叫作 CSS modules 的技術就意在把JS的模塊化思想帶入CSS中來,經過CSS模塊,全部的類名,動畫名默認都只做用於當前模塊。

Webpack從一開始就對CSS模塊化提供了支持,在CSS loader中進行配置後,你所須要作的一切就是把」modules「傳遞到所須要的地方,而後就能夠直接把CSS的類名傳遞到組件的代碼中,且這樣作只對當前組件有效,沒必要擔憂在不一樣的模塊中使用相同的類名形成衝突。

具體的代碼以下

module.exports = {
    ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }
                ]
            }
        ]
    }
};複製代碼

在app文件夾下建立一個Greeter.css文件

.root {
  background-color: #eee;
  padding: 10px;
  border: 3px solid #ccc;
}複製代碼

導入.root到Greeter.js中

import React, {Component} from 'react';
import config from './config.json';
import styles from './Greeter.css';//導入
class Greeter extends Component{
  render() {
    return (
      <div className={styles.root}>//添加類名
        {config.greetText}
      </div>
    );
  }
}
export default Greeter複製代碼

放心使用把,相同的類名也不會形成不一樣組件之間的污染。

應用了css module後的樣式

CSS modules 也是一個很大的主題,有興趣的話能夠去官方文檔查看更多消息

CSS預處理器

Sass 和 Less 之類的預處理器是對原生CSS的拓展,它們容許你使用相似於variables, nesting, mixins, inheritance等不存在於CSS中的特性來寫CSS,CSS預處理器能夠這些特殊類型的語句轉化爲瀏覽器可識別的CSS語句。

你如今可能都已經熟悉了,在webpack裏使用相關loaders進行配置就可使用了,如下是經常使用的CSS 處理loaders:

  • Less Loader
  • Sass Loader
  • Stylus Loader

不過其實也存在一個CSS的處理平臺-PostCSS,它能夠幫助你的CSS實現更多的功能,在其官方文檔可瞭解更多相關知識。


舉例來講如何使用PostCSS,咱們使用PostCSS來爲CSS代碼自動添加適應不一樣瀏覽器的CSS前綴。

首先安裝postcss-loader 和 autoprefixer(自動添加前綴的插件)

npm install --save-dev postcss-loader autoprefixer複製代碼

接下來,在webpack配置文件中添加postcss-loader,在根目錄新建postcss.config.js,並添加以下代碼以後,從新使用npm start打包時,你寫的css會自動根據Can i use裏的數據添加不一樣前綴了。

//webpack.config.js
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }, {
                        loader: "postcss-loader"
                    }
                ]
            }
        ]
    }
}複製代碼
// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}複製代碼

加載Sass

zyx456:成功

運行以下命令來安裝

npm install style-loader css-loader sass-loader node-sass extract-text-webpack-plugin -D複製代碼

安裝:

yarn add --dev sass-loader node-sass複製代碼

而後加一條規則:

module.exports = {
  // …
  module: {
    rules: [
      {
        test: /\.(sass|scss)$/,
        use: [
          "style-loader",
          "css-loader",
          "sass-loader",
        ]
      }
      // …
    ],
  },
};複製代碼

這時候 JavaScript 文件裏就能夠用 import 來引用 .scss 或者 .sass 文件。

使用:

import './scss/base.scss'複製代碼

或者打包成單獨的CSS文件。

webpack.config.js

output: {
  ...
},
module: {
  rules: [
    {
      test: /\.scss$/,
      use: ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: ['css-loader', 'sass-loader']
      })
    }
  ]
}複製代碼

這將告訴webpack,咱們但願將全部CSS打包成一個單獨的文件,並將其稱爲style.css 。

plugins: [
  new ExtractTextPlugin('style.css')
]複製代碼

在head標籤中引入css文件:

<link rel='stylesheet' href='dist/style.css'>複製代碼

插件會報錯:

Error: Chunk.entrypoints: Use Chunks.groupsIterable and filter by instanceof Entrypoint instead

緣由:

extract-text-webpack-plugin還不能支持webpack4.0.0以上的版本。

解決辦法:

npm install extract-text-webpack-plugin@next --save-dev

會下載到+ extract-text-webpack-plugin@4.0.0-beta.0

而後在打包就正常了。

圖片.png

加載圖片

CSS中的背景和圖標,怎麼辦?

使用 file-loader,咱們能夠輕鬆地將這些內容混合到 CSS 中:

npm install --save-dev file-loader複製代碼

webpack.config.js

const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
       {
         test: /\.(png|svg|jpg|gif)$/,
         use: [
           'file-loader'
         ]
       }
      ]
    }
  };複製代碼

用法:

import MyImage from './my-image.png'複製代碼

該圖像將被處理並添加到 output 目錄,而且 MyImage 變量將包含該圖像在處理後的最終 url。

在 Webpack 中使用公用 CDN

module.exports={ externals: {    moment: true
  }
}複製代碼

固然了 HTML 代碼裏須要加上一行

<script src="//apps.bdimg.com/libs/moment/2.8.3/moment-with-locales.min.js"></script>複製代碼

當第三方庫,不支持CommonJS或AMD時。或者須要前置庫時。

有時候會要加載各類各樣的第三方庫,一些老的庫不支持AMD或者CommonJS等一些先進的格式,好比一些jQuery的插件,它們都依賴jQuery,若是直接引用就會報錯 jQuery is not undefined這類的錯誤,有幾種方法解決。

先建立一個jQuery plugin: plugin.js

(function ($) {
    const shade = "#556b2f";
    $.fn.greenify = function() {
        this.css( "color", shade );
        return this;
    };
}(jQuery));複製代碼


第一種方法:使用webpack.ProvidePlugin

ProvidePlugin

webpack提供一個插件把一個全局變量插入到全部的代碼中,在webapck.config.js裏面配置

能夠將模塊做爲一個變量,被 webpack 在其餘每一個模塊中引用。

只有須要使用此變量的時候,這個模塊纔會被 require 進來。

多數以前遺留的模塊,會依賴於已存在的某些特定全局變量,好比 jQuery 插件中的 $ 或者 jQuery。

在這種場景,你能夠在每次遇到全局標識符 $ 的時候,在 webpack 中預先設置

var $ = require(「jquery」)。

...
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Hello World app'
    }),
    //provide $, jQuery and window.jQuery to every script
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
  ...複製代碼

在js中引用

...
//這個也不須要了 由於$, jQuery, window.jQuery均可以直接使用了
//import $ from 'jquery';
import './plugin.js';
...
myPromise.then((number) => {
  $('body').append('<p>promise result is ' + number + ' now is ' + moment().format() + '</p>');
  //call our jquery plugin!
  $('p').greenify();
});
...複製代碼

發現咱們插入的p裏面的顏色已經變成了綠色!

第二種方法:使用imports-loader

先安裝這個loader

imports-loader

npm install imports-loader --save-dev複製代碼

而後在入口js中

//注意這種寫法 咱們把jQuery這個變量直接插入到plugin.js裏面了
//至關於在這個文件的開始添加了 var jQuery = require('jquery');
import 'imports?jQuery=jquery!./plugin.js';
//後面的代碼同樣
myPromise.then((number) => {
  $('body').append('<p>promise result is ' + number + ' now is ' + moment().format() + '</p>');
  //call our jquery plugin!
  $('p').greenify();
});複製代碼
相關文章
相關標籤/搜索