webpack入門(2)

webpack入門(2)

ps:每一個案例都是基於前一個案例改造的javascript

webpack入門(1) 戳這裏css

案例源碼戳這裏html




12、ProvidePlugin

自動加載模塊java

new webpack.ProvidePlugin()node

上面的案例太複雜,下面再新建一個簡單的項目來說解react




案例16 -- 全局引入jquery

新建一個項目,以下jquery

[webpack]
  |-- src
    |-- index.html
    |-- index.less
    |-- index.js
  |-- package.json
  |-- webpack.config.js

webpack/package.jsonwebpack

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "webpack-dev-server --content-base build --inline --hot",
    "build": "webpack -p",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "jquery": "^3.2.1",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.5"
  }
}

webpack/webpack.config.jsgit

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js',
    jquery: [ "jquery" ]
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  module: {
    loaders: [
      {
        test: /\.js$/,  // js-loader
        loader: 'babel-loader?presets=es2015'
      },
      {
        test: /\.css$/, // css-loader
        loader: ExtractTextPlugin.extract('css-loader')
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index', 'jquery'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'jquery' // 對應entry的key
    }),
    new webpack.ProvidePlugin({ // 全局引入jquery
      $: 'jquery'
    })
  ]
}

webpack/src/index.htmlgithub

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpackDemo</title>
</head>
<body>
  
</body>
</html>

webpack/src/index.less

body {
  background: lightpink;
}

webpack/src/index.js

import './index.less';
$('body').prepend('hi');

在webpack.config.js裏設置了全局引入jquery,這裏就不須要

import $ from 'jquery'

能夠直接用 $

$ npm run start , 打開 http://localhost:8080/index.html , 效果以下

39




十3、iconfont

點擊這裏下載 案例17 使用的iconfont文件,如下簡稱「案例17壓縮包」




案例17

新增文件 iconfont.less 和 iconfont.ttf(案例17壓縮包裏的iconfont.ttf),將index.less移動至css文件夾下,以下

[webpack]
  |-- src
    |-- images
      |-- iconfont.ttf
    |-- css
      |-- iconfont.less
      |-- index.less
    |-- index.html
    |-- index.js
  |-- package.json
  |-- webpack.config.js

webpack/src/css/iconfont.less

@font-face {
  font-family: "iconfont";
  src: url('../images/iconfont.ttf') format('truetype');
}
.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
.icon-love:before { content: "\e612"; }

webpack/src/css/index.less

@import './iconfont.less';
body {
  background: lightpink;
  .iconfont {
    font-size: 50px;
  }
}

webpack/src/index.js

import './css/index.less';
$('body').prepend('<i class="iconfont icon-love"></i>');

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js',
    jquery: [ "jquery" ]
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  module: {
    loaders: [
      {
        test: /\.js$/,  // js-loader
        loader: 'babel-loader?presets=es2015'
      },
      {
        test: /\.css$/, // css-loader
        loader: ExtractTextPlugin.extract('css-loader')
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index', 'jquery'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'jquery' // 對應entry的key
    }),
    new webpack.ProvidePlugin({ // 全局引入jquery
      $: 'jquery'
    })
  ]
}

本案例只引入了ttf,其餘能夠相似添加

{
  test: /\.(png|jpg|ttf|svg|eot|woff)$/, // img-loader
  loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
}

$ npm run start , 打開 http://localhost:8080/index.html ,效果以下

40

$ npm run build , iconfont.ttf文件小會轉爲base64直接打包到index.css裏,若是文件比較大,則會單獨打包到webpack/build/images/iconfont.ttf




十4、externals

externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法。

好比 jquery 但願經過 cdn 的方式引入,代碼裏依舊用 import 的方式來使用,可是又不但願被打包。




案例18

webpack/src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpackDemo</title>
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>

webpack/src/index.js

import $ from 'jquery';
import './css/index.less';
$('body').prepend('<i class="iconfont icon-love"></i>');

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    jquery: 'jQuery' // jquery不被webpack編譯到文件中
  },
  module: {
    loaders: [
      {
        test: /\.js$/,  // js-loader
        loader: 'babel-loader?presets=es2015'
      },
      {
        test: /\.css$/, // css-loader
        loader: ExtractTextPlugin.extract('css-loader')
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

運行 $ npm run build , 生成文件目錄以下

[webpack]
  |-- build
    |-- index.css
    |-- index.html
    |-- index.js




十5、react

安裝依賴
$ npm i babel-preset-react react react-dom --save-dev




案例19

webpack/src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpackDemo</title>
</head>
<body>
  <div id="root"></div>
</body>
</html>

webpack/src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './css/index.less';

class Demo extends React.Component {
  render() {
    return (
      <i  className="iconfont icon-love" />
    );
  }
}

ReactDOM.render(
  <Demo />,
  document.getElementById('root')
);

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.css$/, // css-loader
        loader: ExtractTextPlugin.extract('css-loader')
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

須要babel-preset-react插件來編譯React

運行 $ npm run start , 打開 http://localhost:8080/ ,能看到效果

運行 $ npm run build ,打包文件目錄以下:

[webpack]
  |-- build
    |-- index.css
    |-- index.html
    |-- index.js

react被打包到webpack/build/index.js裏去了




案例20 -- react 經過 cdn 的方式引入

webpack/src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpackDemo</title>
</head>
<body>
  <div id="root"></div>
  <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
  <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
</body>
</html>

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'react': 'React',
    'react-dom': 'ReactDOM'
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.css$/, // css-loader
        loader: ExtractTextPlugin.extract('css-loader')
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

這樣 react 就不會被打包入 webpack/build/index.js




十6、devServer

  • hot : boolean , 啓用 webpack 的模塊熱替換特性
  • inline : boolean , 內聯模式(默認) , false 時爲 iframe 模式
  • contentBase : boolean|string|array , 設定webpack-dev-server的director根目錄。若是不進行設定的話,默認是在當前目錄下。
  • compress : boolean , 一切服務都啓用 gzip 壓縮
  • port : number , 指定要監聽請求的端口號
  • host : string , 指定使用一個 host
  • proxy : object , webpack 代理
  • filename : string , 能夠只在某個文件時被請求時編譯
  • headers : object , 在全部請求中添加首部內容

更多參數戳這裏




案例21

新建一個項目以下

[webpack]
  |-- package.json
  |-- webpack.config.js
  |-- src
    |-- index.html
    |-- index.js
    |-- images
      |-- SpongeBob.jpg
    |-- css
      |-- index.less

本案例用到的圖片 SpongeBob.jpg 戳這裏

webpack/package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "webpack-dev-server",
    "build": "webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "jquery": "^3.2.1",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.5"
  }
}

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  devServer: {
    contentBase: './build',
    inline: true,
    hot: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

webpack/src/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>webpackDemo</title>
</head>
<body>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>

webpack/src/css/index.less

body {
  background: url(../images/SpongeBob.jpg) no-repeat;
  color: blue;
}

webpack/src/index.js

import './css/index.less';

$('body').prepend('hi')

package.json 對比

// 案例16
"scripts": {
  "start": "webpack-dev-server --content-base build --inline --hot",
}
// 案例21
"scripts": {
  "start": "webpack-dev-server",
}

案例21 中 webpack-dev-server 後的參數,改成在 webapck.config.js 中設置

{
  devServer: {
    contentBase: './build',
    inline: true,
    hot: true
  },
  plugins: [ new webpack.HotModuleReplacementPlugin() ]
}

$ npm run start , 打開 http://localhost:8080/ , 效果以下

41




十7、本地 mock 模擬後端數據

{
  devServer: {
    before: (app) =>{
      app.get('/init.json', function(req, res) {
        res.json({ title: 'webpack' });
      });
    }
  }
}




案例22

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  devServer: {
    contentBase: './build',
    inline: true,
    hot: true,
    before: (app) =>{
      app.get('/init.json', function(req, res) {
        res.json({ title: 'webpack' });
      });
    }
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

webpack/src/index.js

import './css/index.less';

$.ajax({
  url: '/init.json',
  data: {},
  type: 'GET',
  success: (d = {}) => {
    $('body').prepend(d.title);
  },
  error: () => {
    $('body').prepend('ajax error');
  }
});

$ npm run start , 打開 http://localhost:8080/index.html , 效果以下

42

若是是 post 請求,webpack.config.js 以下

{
  devServer: {
    before: (app) =>{
      app.post('/init.json', function(req, res) {
        res.json({ title: 'webpack' });
      });
    }
  }
}

固然,也能夠不在 res.json() 中直接寫 mock 數據,能夠在外面命名變量,或者從其餘文件引入

var mock_init = require('xxxxx');
var mock_user = { title: 'webpack' };
module.exports = {
  devServer: {
    before: (app) =>{
      app.post('/init.json', function(req, res) {
        res.json(mock_init);
      });
      app.post('/user.json', function(req, res) {
        res.json(mock_user);
      });
    }
  }
}




十8、環境變量

DefinePlugin 能夠把命令行的環境變量帶到瀏覽器端。

new webpack.DefinePlugin()

詳解戳這裏




案例23

環境變量在不少狀況都會使用,這裏舉一個例子,好比咱們本地 mock 數據時,請求都是 "localhost:8080" 開頭的,可是到線上了則是 "http://a.com" 和 "http://b.com" , 這個時候就可使用 DefinePlugin 來解決

webpack/package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "NODE_ENV=mock webpack-dev-server",
    "prod": "NODE_ENV=prod webpack-dev-server",
    "build-start": "NODE_ENV=mock webpack -p",
    "build-prod": "NODE_ENV=prod webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "jquery": "^3.2.1",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.5"
  }
}

"NODE_ENV=xxx" , 能夠定義不一樣環境的 NODE_ENV

start 和 build-start , 是咱們本地開發時使用 ; prod 和 build-prod , 是線上環境使用

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

console.log('----------- NODE_ENV ----------- : ', process.env.NODE_ENV)

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  devServer: {
    contentBase: './build',
    inline: true,
    hot: true,
    before: (app) =>{
      app.get('/init.json', function(req, res) {
        res.json({ title: 'webpack' });
      });
    }
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

經過 process.env.NODE_ENV 變量拿到值

$ npm run start , 效果以下

43

$ npm run prod , 效果以下

44

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

const checkHost = {
  "mock": {
    "A_HOST": "http://localhost:8080",
    "B_HOST": "http://localhost:8080",
  },
  "prod": {
    "A_HOST": "http://a.com",
    "B_HOST": "http://b.com",
  }
}

var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock';

var checkHostContent = checkHost[checkHostKey];

for (i in checkHostContent) {
  checkHostContent[i] = JSON.stringify(checkHostContent[i]);
}

module.exports = {
  entry: { // 入口文件地址
    index: './src/index.js'
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  devServer: {
    contentBase: './build',
    inline: true,
    hot: true,
    before: (app) =>{
      app.get('/init.json', function(req, res) {
        res.json({ title: 'webpack' });
      });
    }
  },
  plugins: [
    new webpack.DefinePlugin(checkHostContent),
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

分析以下

const checkHost = {
  "mock": { // 本地 mock 數據使用
    "A_HOST": "http://localhost:8080",
    "B_HOST": "http://localhost:8080",
  },
  "prod": { // 線上環境使用
    "A_HOST": "http://a.com",
    "B_HOST": "http://b.com",
  }
}

// 檢查 checkHost[process.env.NODE_ENV] 是否存在,不存在時,將rocess.env.NODE_ENV 設置爲 mock
var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock';

// checkHostContent 至關因而 checkHost.mock 或 checkHost.prod
var checkHostContent = checkHost[checkHostKey];

// 若是 DefinePlugin 鍵值是一個字符串,它會被看成一個代碼片斷來使用,須要 JSON.stringify() 處理
for (i in checkHostContent) {
  checkHostContent[i] = JSON.stringify(checkHostContent[i]);
}

// 將處理好的 checkHostContent 放入
module.exports = {
  plugins: [new webpack.DefinePlugin(checkHostContent)]
}

這一部分代碼,將咱們要用到的 A_HOST 和 B_HOST 都處理好,再放入new webpack.DefinePlugin(),拿 prod 舉例,至關於處理成

module.exports = {
  plugins: [new webpack.DefinePlugin({
    A_HOST: JSON.stringify("http://a.com"),
    B_HOST: JSON.stringify("http://b.com"),
  })]
}

webpack/src/index.js

import './css/index.less';

console.log(A_HOST, B_HOST)

$.ajax({
  url: `${A_HOST}/init.json`,
  data: {},
  type: 'GET',
  success: (d = {}) => {
    $('body').prepend(d.title);
  },
  error: () => {
    $('body').prepend('ajax error');
  }
});

$ npm run start , 效果以下

45

$ npm run prod , 效果以下

46

固然,也能夠直接寫兩個 webpack.config.js 文件,這裏就貼一下代碼,不具體寫案例了

// webpack.start.config.js
module.exports = {
  plugins: [new webpack.DefinePlugin({
    A_HOST: JSON.stringify("http://localhost:8080"),
    B_HOST: JSON.stringify("http://localhost:8080"),
  })]
}

// webpack.prod.config.js
module.exports = {
  plugins: [new webpack.DefinePlugin({
    A_HOST: JSON.stringify("http://a.com"),
    B_HOST: JSON.stringify("http://b.com"),
  })]
}

// package.json
{
  "scripts": {
    "start": "webpack-dev-server --config webpack.start.config.js",
    "prod": "webpack-dev-server --config webpack.prod.config.js",
    "build-start": "webpack -p --config webpack.start.config.js",
    "build-prod": "webpack -p --config webpack.prod.config.js"
  }
}




十9、server.js

詳細介紹戳這裏




案例24

新增 webpack/server.js , 目錄以下

[webpack]
  |-- server.js
  |-- package.json
  |-- webpack.config.js
  |-- src
    |-- index.html
    |-- index.js
    |-- images
      |-- SpongeBob.jpg
    |-- css
      |-- index.less

webpack/webpack.config.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

const checkHost = {
  "mock": { // 本地 mock 數據使用
    "A_HOST": "http://localhost:8080",
    "B_HOST": "http://localhost:8080",
  },
  "prod": { // 線上環境使用
    "A_HOST": "http://a.com",
    "B_HOST": "http://b.com",
  }
}

// 檢查 process.env.NODE_ENV 是否和 checkHost 裏的對應
var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock';

// checkHostContent 至關因而 checkHost.mock 或 checkHost.prod
var checkHostContent = checkHost[checkHostKey];

// 若是 DefinePlugin 鍵值是是一個字符串,它會被看成一個代碼片斷來使用,須要 JSON.stringify() 處理
for (i in checkHostContent) {
  checkHostContent[i] = JSON.stringify(checkHostContent[i]);
}

module.exports = {
  entry: { // 入口文件地址
    index: ['./src/index.js']
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    loaders: [
      {
        test: /\.(js|jsx)$/,  // js-loader
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
      {
        test: /\.less/, // less-loader
        loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      },
      {
        test: /\.(png|jpg|ttf)$/, // img-loader
        loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      }
    ],
  },
  plugins: [
    new webpack.DefinePlugin(checkHostContent), // 將處理好的 checkHostContent 放入
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

將 devServer 刪除 , entry.index 改成 array 寫法

webpack/server.js

// 引入 webpack 和 webpack-dev-server
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');

// 引入 webpack 的配置
var config = require('./webpack.config.js');

// 添加 webpack-dev-server 的客戶端入口文件到 webpack 的配置中
// 經過 unshift 方法,將 webpack-dev-server/client?http://«path»:«port»/ 插入到 webpack-dev-server 配置的 entry.index 中
config.entry.index.unshift("webpack-dev-server/client?http://localhost:8080/");

// compiler = webpack({ webpack 的配置 })
var compiler = webpack(config);

// server = new WebpackDevServer(compiler, { devServer 的配置 })
var server = new WebpackDevServer(compiler, {
  contentBase: './build',
  inline: true,
  hot: true,
  before: (app) =>{
    app.get('/init.json', function(req, res) {
      res.json({ title: 'webpack' });
    });
  }
});

server.listen(8080, "localhost", function() {});

webpack-dev-server 的配置裏沒有 inline : true 這個配置項, 由於 webpack-dev-server 沒法訪問 webpack 的配置。 所以,用戶必須添加 webpack-dev-server 的客戶端入口文件到 webpack 的配置中,有如下幾種方式(上面案例只寫了一種,其餘你們能夠自行嘗試)

// server.js
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");

// webpack.config.js
{
  entry: {
    index: [
     'webpack-dev-server/client?http://localhost:8080/',
     './src/index.js'
    ]
  }
}
// index.html
<script src="http://localhost:8080/webpack-dev-server.js"></script>

webpack/package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "scripts": {
    "start": "NODE_ENV=mock node server.js",
    "prod": "NODE_ENV=prod node server.js",
    "build-start": "NODE_ENV=mock webpack -p",
    "build-prod": "NODE_ENV=prod webpack -p"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.7",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "jquery": "^3.2.1",
    "less": "^2.7.3",
    "less-loader": "^4.0.5",
    "style-loader": "^0.19.0",
    "url-loader": "^0.6.2",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.9.5"
  }
}

修改了 scripts.start 和 scripts.prod ,$ npm run start 和 $ npm run prod ,效果和 案例23 同樣




二10、module.rules

下面介紹一下 loaders 的其餘寫法




案例25

webpack/server.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

const checkHost = {
  "mock": { // 本地 mock 數據使用
    "A_HOST": "http://localhost:8080",
    "B_HOST": "http://localhost:8080",
  },
  "prod": { // 線上環境使用
    "A_HOST": "http://a.com",
    "B_HOST": "http://b.com",
  }
}

// 檢查 process.env.NODE_ENV 是否和 checkHost 裏的對應
var checkHostKey = checkHost[process.env.NODE_ENV] ? process.env.NODE_ENV : 'mock';

// checkHostContent 至關因而 checkHost.mock 或 checkHost.prod
var checkHostContent = checkHost[checkHostKey];

// 若是 DefinePlugin 鍵值是是一個字符串,它會被看成一個代碼片斷來使用,須要 JSON.stringify() 處理
for (i in checkHostContent) {
  checkHostContent[i] = JSON.stringify(checkHostContent[i]);
}

module.exports = {
  entry: { // 入口文件地址
    index: ['./src/index.js']
  },
  output: { // 出口
    path: __dirname + "/build", // 打包後的文件存放路徑
    filename: '[name].js' // 文件名,name即爲entry的key
  },
  externals: {
    'jquery': 'jQuery', // 不打包jquery
  },
  module: {
    rules: [ // loaders
      {
        test: /\.(js|jsx)$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['es2015', 'react']
          }
        }
      },
      {
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          use: [{
            loader: "css-loader"
          }, {
            loader: "less-loader"
          }]
        })
      },
      {
        test: /\.(png|jpg|ttf)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'images/[hash:8].[name].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin(checkHostContent), // 將處理好的 checkHostContent 放入
    new webpack.HotModuleReplacementPlugin(), // 啓用熱替換模塊
    new HtmlWebpackPlugin({
      filename: 'index.html', // 生成的的html文件名
      template: './src/index.html', // 被打包的html路徑
      chunks: ['index'] // 須要引入的js,對應entry的key
    }),
    new ExtractTextPlugin({ // 單獨打包css
      filename: '[name].css'
    })
  ]
}

對比分析以下

{
  module: {
    // module.loaders 改成 module.rules
    rules: [
      // {
      //   test: /\.(js|jsx)$/,  // js-loader
      //   loader: 'babel-loader?presets[]=es2015&presets[]=react'
      // }
      {
        test: /\.(js|jsx)$/,
        use: {
          loader: 'babel-loader',
          options: { // ? 後的參數能夠寫在這裏
            presets: ['es2015', 'react']
          }
        }
      },
      // {
      //   test: /\.less/, // less-loader
      //   loaders: ExtractTextPlugin.extract('css-loader!less-loader')
      // }
      {
        test: /\.less$/,
        use: ExtractTextPlugin.extract({
          use: [{
            loader: "css-loader"
          }, {
            loader: "less-loader"
          }]
        })
      },
      // {
      //   test: /\.(png|jpg|ttf)$/, // img-loader
      //   loader: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
      // }
      {
        test: /\.(png|jpg|ttf)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192,
              name: 'images/[hash:8].[name].[ext]'
            }
          }
        ]
      }
    ]
  }
}
相關文章
相關標籤/搜索