請練完這16個webpack小例子

16個demo,webpack+react搭配使用javascript

首先教你們2個新技能css

  • 1.按照正常github地址狀況下,你的github自己不能訪問目錄。html

  • 2.github目錄的製做vue

    • 明確一個問題。一個標題就是一個目錄名稱java

    • 寫法[xx](#題目名稱)#不能少node

    • 題目名稱的寫法規則:abc demo-> abc-demo,Abc-Demo->abc-demo。會忽略:和()即就是題目中全部可見字符的空格均用-鏈接,中、英文空格要分開,中文空格對應中文-。而且全爲小寫react

步驟

首先,install Webpackwebpack-dev-server.jquery

$ npm i -g webpack webpack-dev-server
# Linux & Mac
$ git clone git@github.com:holidaying/webpack-demo.git

# Windows
$ git clone https://github.com/holidaying/webpack-demo.git
:
$ cd webpack-demos
$ npm install

接下來就能夠進行demo演示了.webpack

$ cd demo01
$ webpack-dev-server

用瀏覽器訪問 http://127.0.0.1:8080.

什麼是webpack?

Webpack 是前端的打包工具類相似於 Grunt and Gulp.可是有區別,由於它是模塊化構建機制,Webpack能夠看作是模塊打包機:它作的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包爲合適的格式以供瀏覽器使用。
WebPack和Grunt以及Gulp相比有什麼特性
其實Webpack和另外兩個並無太多的可比性,Gulp/Grunt是一種可以優化前端的開發流程的工具,而WebPack是一種模塊化的解決方案,不過Webpack的優勢使得Webpack能夠替代Gulp/Grunt類的工具。
Grunt和Gulp的工做方式是:在一個配置文件中,指明對某些文件進行相似編譯,組合,壓縮等任務的具體步驟,這個工具以後能夠自動替你完成這些任務。
更多信息.

$ webpack main.js bundle.js

它的配置文件是 webpack.config.js.

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

有了webpack.config.js,你能夠不帶參數使用webpack

$ webpack

一些命令行選項你應該知道。

  • webpack – 構建文件

  • webpack -p – 發佈

  • webpack --watch – 監聽項目

  • webpack -d – 包含 source maps方便調試

  • webpack --colors – 讓打包界面更好看

去構建你的項目, 你能夠把啓動項寫進package.json

// package.json
{
  // ...
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "deploy": "NODE_ENV=production webpack -p"
  },
  // ...
}

目錄

  1. 單文件入口

  2. 多文件入口

  3. Babel-loader

  4. CSS-loader

  5. Image loader

  6. CSS Module

  7. UglifyJs Plugin插件

  8. HTML Webpack Plugin and Open Browser Webpack Plugin

  9. Environment flags環境變量

  10. Code splitting代碼分割

  11. Code splitting with bundle-loader

  12. Common chunk提取公共文件

  13. Vendor chunk提取公共的第三方代碼

  14. externals全局變量

  15. 熱模塊替代/熱更新

  16. React router

Demo01: 單文件入口 (源碼)

Webpack會入口文件進行打包成bundle.js.

例子, main.js 是單文件入口.

// main.js
document.write('<h1>Hello World</h1>');

index.html

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

Webpack follows webpack.config.js to build bundle.js.

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

啓動服務, 訪問 http://127.0.0.1:8080 .

$ webpack-dev-server

Demo02: 多文件入口(源碼)

多個入口文件,實用於多個頁面的應用

// main1.js
document.write('<h1>Hello World</h1>');

// main2.js
document.write('<h2>Hello Webpack</h2>');

index.html

<html>
  <body>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: {
    bundle1: './main1.js',
    bundle2: './main2.js'
  },
  output: {
    filename: '[name].js'
  }
};

Demo03: Babel-loader (源碼)

經過使用不一樣的loader,webpack經過調用外部的腳本或工具能夠對各類各樣的格式的文件進行處理(更多信息). 例如, Babel-loader Babel實際上是一個編譯JavaScript的平臺能夠將 JSX/ES6 文件轉換成瀏覽器能夠識別的js文件. 官方文檔loaders.

main.jsx is a JSX 文件.

const React = require('react');
const ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.querySelector('#wrapper')
);

index.html

<html>
  <body>
    <div id="wrapper"></div>
    <script src="bundle.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.jsx',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader?presets[]=es2015&presets[]=react'
      },
    ]
  }
};

webpack.config.js, module.loaders 區域是用來分配loader的. 像上面的代碼片斷使用了 babel-loader 須要安裝插件 babel-preset-es2015babel-preset-react to 編譯成 ES6 and React. 能夠用query配置參數

module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel',
      query: {
        presets: ['es2015', 'react']
      }
    }
  ]
}

Demo04: CSS-loader (源碼)

Webpack 容許你在js文件中require CSS , 經過 CSS-loader來預處理css文件.

main.js

require('./app.css');

app.css

body {
  background-color: blue;
}

index.html

<html>
  <head>
    <script type="text/javascript" src="bundle.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.css$/, loader: 'style-loader!css-loader' },
    ]
  }
};

可是,你須要使用2中loaders來轉換CSS 文件. 第一個是 CSS-loader 來讀取CSS文件, 另一個是Style-loader 是將style樣式插入到html中。 中間用!鏈接

啓動服務後, index.html 有內部樣式.

<head>
  <script type="text/javascript" src="bundle.js"></script>
  <style type="text/css">
    body {
      background-color: blue;
    }
  </style>
</head>

Demo05: Image loader (源碼)

Webpack 容許你在js文件中require圖片 , 經過 url-loader和file-loader來預處理圖片文件.

main.js

var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);

var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

index.html

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
    ]
  }
};

url-loader 轉換圖片文件. 若是圖片的大小小於 8192 bytes,它將會轉成base64位的地址; 相反, 它就是普通地址.
參數前是用?鏈接的

啓動服務後, small.png and big.png 將會有一下的地址.

<img src="data:image/png;base64,iVBOR...uQmCC">
<img src="4853ca667a2b8b8844eb2693ac1b2578.png">

Demo06: CSS Module (源碼)

css-loader?modules (the query parameter modules) enables the CSS Modules spec.

CSS Module能夠開啓全局變量和局部變量,:global(...)表示全局變量,能夠在全局中使用樣式(更多信息)

index.html

<html>
<body>
  <h1 class="h1">Hello World</h1>
  <h2 class="h2">Hello Webpack</h2>
  <div id="example"></div>
  <script src="./bundle.js"></script>
</body>
</html>

app.css

.h1 {
  color:red;
}

:global(.h2) {
  color: blue;
}

main.jsx

var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');

ReactDOM.render(
  <div>
    <h1 className={style.h1}>Hello World</h1>
    <h2 className="h2">Hello Webpack</h2>
  </div>,
  document.getElementById('example')
);

webpack.config.js

module.exports = {
  entry: './main.jsx',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader?modules'
      }
    ]
  }
};

啓動服務.

$ webpack-dev-server

訪問 http://127.0.0.1:8080 , 你將看到只有第二個 h1 是紅的,由於它是局部, 同時 h2 是藍色的, 由於是h2全局的.

Demo07: UglifyJs Plugin (源碼)

Webpack 能夠去掉自己附加的東西,優化代碼 UglifyJs Plugin will minify output(bundle.js) JS codes.

main.js

var longVariableName = 'Hello';
longVariableName += ' World';
document.write('<h1>' + longVariableName + '</h1>');

index.html

<html>
<body>
  <script src="bundle.js"></script>
</body>
</html>

webpack.config.js

var webpack = require('webpack');
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new uglifyJsPlugin({
      compress: {
        warnings: false
      }
    })
  ]
};

啓動服務後, main.js 將會壓縮以下.

var o="Hello";o+=" World",document.write("<h1>"+o+"</h1>")

Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin (源碼)

這個例子須要加載三個插件

html-webpack-plugin 建立 index.htmlopen-browser-webpack-plugin 打開瀏覽器

main.js

document.write('<h1>Hello World</h1>');

webpack.config.js

var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Webpack-demos',
      filename: 'index.html'
    }),
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    })
  ]
};

啓動 webpack-dev-server.啓動這個須要node7版本以上

$ webpack-dev-server

不用手寫index.html 也不用手動打開瀏覽器 Webpack 能夠爲你作這些事.

Demo09: 設置環境變量 (源碼)

你能夠利用環境變量來控制特定代碼的輸出

main.js

document.write('<h1>Hello World</h1>');

if (__DEV__) {
  document.write(new Date());
}

index.html

<html>
<body>
  <script src="bundle.js"></script>
</body>
</html>

webpack.config.js

var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [devFlagPlugin]
};
# Linux & Mac
$ env DEBUG=true webpack-dev-server

# Windows
$ set DEBUG=true
$ webpack-dev-server

Demo10: Code splitting (源碼)

對於大型項目,把全部代碼編譯到一個文件並非有效的, Webpack 容許你把代碼分紅好多塊. 特別是某種狀況下,只須要個別代碼這些塊能夠按需加載。
在commonjs中有一個Modules/Async/A規範,裏面定義了require.ensure語法。webpack實現了它,做用是能夠在打包的時候進行代碼分片,並異步加載分片後的代碼。用法以下:

require.ensure([], function(require){
    var list = require('./list');
    list.show();
});

此時list.js會被打包成一個單獨的chunk文件,大概長這樣:
1.fb874860b35831bc96a8.js
可讀性比較差。我在上一篇結尾也提到了,給它命名的方式,那就是給require.ensure傳遞第三個參數,如:

require.ensure([], function(require){
    var list = require('./list');
    list.show();
}, 'list');

這樣就能獲得你想要的文件名稱:
首先,你須要用 require.ensure to 來定義一個分割的點. (官方文檔)

// main.js
require.ensure(['./a'], function(require) {
  var content = require('./a');
  document.open();
  document.write('<h1>' + content + '</h1>');
  document.close();
});

require.ensure 告訴 Webpack ./a.js 應該從 bundle.js 中分離成一個單獨的塊

// a.js
module.exports = 'Hello World';

Now Webpack takes care of the dependencies, output files and runtime stuff. You don't have to put any redundancy into your index.html and webpack.config.js.

<html>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

webpack.config.js

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};

啓動服務.

$ webpack-dev-server

在界面上, 你感受不到任何不同的地方. 可是, Webpack 已經把 main.jsa.js 編譯成(bundle.js1.bundle.js)的塊。

Demo11: 經過bundle-loader進行代碼分裂 (源碼)

dem10是一種,另外一種是利用bundle-loader.

// main.js

// Now a.js is requested, it will be bundled into another file
var load = require('bundle-loader!./a.js');

// To wait until a.js is available (and get the exports)
//  you need to async wait for it.
load(function(file) {
  document.open();
  document.write('<h1>' + file + '</h1>');
  document.close();
});

require('bundle-loader!./a.js') tells Webpack to load a.js from another chunk.

Now Webpack will build main.js into bundle.js, and a.js into 1.bundle.js.

Demo12: Common chunk (源碼)

利用webpack.optimize.CommonsChunkPlugin,你能夠共通的組件,代碼塊分離出來

// main1.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>Hello World</h1>,
  document.getElementById('a')
);

// main2.jsx
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h2>Hello Webpack</h2>,
  document.getElementById('b')
);

index.html

<html>
  <body>
    <div id="a"></div>
    <div id="b"></div>
    <script src="init.js"></script>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

webpack.config.js

var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
  entry: {
    bundle1: './main1.jsx',
    bundle2: './main2.jsx'
  },
  output: {
    filename: '[name].js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
    ]
  },
  plugins: [
    new CommonsChunkPlugin('init.js')
  ]
}

Demo13: Vendor chunk (源碼)

利用webpack.optimize.CommonsChunkPlugin,你能夠把第三方庫抽離出來

main.js

var $ = require('jquery');
$('h1').text('Hello World');

index.html

<html>
  <body>
    <h1></h1>
    <script src="vendor.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

webpack.config.js

var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js',
    vendor: ['jquery'],
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js')
  ]
};

If you want a module available as variable in every module, such as making $ and jQuery available in every module without writing require("jquery"). You should use ProvidePlugin (官方文檔).

// main.js
$('h1').text('Hello World');


// webpack.config.js
var webpack = require('webpack');

module.exports = {
  entry: {
    app: './main.js'
  },
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
};

插件會執行兩次這個方法,第一次將公共的第三方代碼抽離移到vendor的塊中,這個過程以前也講過會將運行時runtime也轉移到vendor塊中,第二次執行則是將運行時runtime抽離出來轉移到manifest塊中。這步操做解決了緩存問題。
這樣處理,最後會生成3個打包文件chunk,app.js是業務代碼,vendor則是公共的第三方代碼,manifest.js則是運行時。

Demo14: Exposing global variables (源碼)

webpack能夠不處理應用的某些依賴庫,使用externals配置後,依舊能夠在代碼中經過CMD、AMD或者window/global全局的方式訪問。若是你想引入一些全局變量, 可是不想被加載處理, 你能夠在 webpack.config.js 使用 externals 模塊 (官方文檔).
有時咱們但願咱們經過script引入的庫,如用CDN的方式引入的jquery,咱們在使用時,依舊用require的方式來使用,可是卻不但願webpack將它又編譯進文件中。
<script src="http://code.jquery.com/jquery...
例子, data.js.

var data = 'Hello World';

We can expose data as a global variable.

// webpack.config.js
module.exports = {
  entry: './main.jsx',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
    ]
  },
  externals: {
    // require('data') is external and available
    //  on the global var data
    'data': 'data'
  }
};

如今, 你能夠require data 做爲模塊化引入進來使用. 可是其實是一個全局變量

// main.jsx
var data = require('data');
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>{data}</h1>,
  document.body
);

Demo15: 熱模塊替換/熱更新 (源碼)

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running without a page reload.

經過webpack-dev-server.你可使用2中方式 來進行熱模塊替換

(1) Specify --hot and --inline on the command line

$ webpack-dev-server --hot --inline

參數的意思:

  • --hot: adds the HotModuleReplacementPlugin and switch the server to hot mode.

  • --inline: embed the webpack-dev-server runtime into the bundle.

  • --hot --inline: also adds the webpack/hot/dev-server entry.

(2) 修改 webpack.config.js.

  • 添加 new webpack.HotModuleReplacementPlugin() to the plugins 模塊

  • 添加 webpack/hot/dev-serverwebpack-dev-server/client?http://localhost:8080 to the entry 模塊

webpack.config.js 以下所示.

var webpack = require('webpack');
var path = require('path');

module.exports = {
  entry: [
    'webpack/hot/dev-server',
    'webpack-dev-server/client?http://localhost:8080',
    './index.js'
  ],
  output: {
    filename: 'bundle.js',
    publicPath: '/static/'
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015', 'react']
      },
      include: path.join(__dirname, '.')
    }]
  }
};

啓動服務

$ webpack-dev-server

訪問 http://localhost:8080, 你能夠在瀏覽器上看到 'Hello World' .

不要關閉服務.打開終端找到 App.js, 同時修改 'Hello World' 爲 'Hello Webpack'. 保存後,你就能夠在瀏覽器上看到數據更新了

App.js

import React, { Component } from 'react';

export default class App extends Component {
  render() {
    return (
      <h1>Hello World</h1>
    );
  }
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

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

index.html

<html>
  <body>
    <div id='root'></div>
    <script src="/static/bundle.js"></script>
  </body>
</html>

Demo16: React router例子 (源碼)

利用webpack作的例子 React-router's 官方例子.

Let's imagine a little app with a dashboard, inbox, and calendar.

+---------------------------------------------------------+
| +---------+ +-------+ +--------+                        |
| |Dashboard| | Inbox | |Calendar|      Logged in as Jane |
| +---------+ +-------+ +--------+                        |
+---------------------------------------------------------+
|                                                         |
|                        Dashboard                        |
|                                                         |
|                                                         |
|   +---------------------+    +----------------------+   |
|   |                     |    |                      |   |
|   | +              +    |    +--------->            |   |
|   | |              |    |    |                      |   |
|   | |   +          |    |    +------------->        |   |
|   | |   |    +     |    |    |                      |   |
|   | |   |    |     |    |    |                      |   |
|   +-+---+----+-----+----+    +----------------------+   |
|                                                         |
+---------------------------------------------------------+
$ webpack-dev-server --history-api-fallback

參照文檔

免費送上UI資源庫

全文參考阮老師的教程。

相關文章
相關標籤/搜索