(翻譯)阮一峯老師的webpack使用教程

文章說明

這篇文章是在看阮一峯老師在GitHub上發表的webpack學習文檔的時候,翻譯出的文檔說明webpack 阮一峯教程 ,純手打非機翻。javascript

最後兩個demo沒有打上來,翻譯好會補上來。文中有一小部分文字是我針對這個知識點的理解,就幾行。css

若是有錯誤,歡迎指出。html

再次感謝阮一峯老師。前端

什麼是webpack

前端構建工具,與gulp和grunt 相似java

做爲打包工具,與browserify 相似node

# be equivalent to
$ webpack main.js bundle.js
複製代碼

配置文件是 webpack.config.jsreact

  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};
複製代碼

常見的命令們jquery

  • webpack 供開發構建
  • webpack -p 供生產構建一次
  • webpack --watch – 連續的增量構建
  • webpack -d – 包括源地圖
  • webpack --colors – 讓內部更好看

生產環境的應用須要在package.json中配置script :webpack

    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "deploy": "NODE_ENV=production webpack -p"
  },
複製代碼

入口文件

就是第一個進入的文件,使用入口文件進行打包或者構建 demo1中的bundle.jsgit

在demo1 的例子中, main.js是入口文件

複製代碼

在index.html 中:

  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>
複製代碼

webpack 會按照webpack.config.js 去構建 bundle.js

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

使用命令webpack-dev-server 啓動服務器

多入口文件

對於多頁面網站,適合使用多個入口文件

在main1.js 和main2.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'
  }
};
複製代碼

babel-loader

loader 是預處理器,讓webpack處理非js文件,將全部的文件轉換爲webpack可以處理的有效模塊

loader的兩個目標

  • 識別出應該被loader轉化的文件, 使用test屬性
  • 轉換這些文件,使他們添加到依賴圖中,最終添加到bundle中,使用use屬性

babel-loader 是一個將jsx、es6格式的文件轉換爲js文件的工具。

在main.jsx中:

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

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

在index.html 中

  <body>
    <div id="wrapper"></div>
    <script src="bundle.js"></script>
  </body>
</html>
複製代碼

webpack.config.js

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

在config.js中,module.loaders 用來分配loaders,上面的插件使用了babel-loader,babel-preset-es2015,babel-preset-react 進行編譯,test用來檢測識別

還能夠這樣寫

  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: 'babel-loader',
      query: {
        presets: ['es2015', 'react']
      }
    }
  ]
}
複製代碼

css-loader

能夠預處理css 文件使用css—loader

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' },
    ]
  }
};
複製代碼

這裏須要注意到是,必須使用兩個加載器來轉換,css-loader 是用來讀取cssfile,style-loader是用來將style標籤插入到html頁面的,不一樣的loader使用‘!’來鏈接

image loader

一樣,圖片資源也能夠在js 文件中 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轉換image文件,若是小於8192不用特殊,就能夠轉化成數據url,否則的化就是正常的url。‘?’是用來給loader傳遞參數的

轉化以後的圖片以下:

<img src="data:image/png;base64,iVBOR...uQmCC">---小圖
<img src="4853ca667a2b8b8844eb2693ac1b2578.png"> ---大圖
複製代碼

css模塊

使用css-loader?modules能夠知足css模塊的需求

main.js

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')
);
複製代碼

app.css

.h1 {
  color:red;
}

:global(.h2) {
  color: blue;
}
複製代碼

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>
複製代碼

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'
      }
    ]
  }
};
複製代碼

若是是css模塊是行成本身的做用域?能夠使用:global來進行開關 在上面的例子中只有第二個h1是紅色的,由於css被本地做用域化了,兩個h2都是藍的,由於是全局的

uglify

webpack有不少管道系統來擴展他的功能,uglify是用來壓縮js代碼的

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
      }
    })
  ]
};
複製代碼

使用plugins 來使用uglify,在exports的上面定義uglify

var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

以及使用plugins 來使用uglify

加載第三方管道

html-webpack-plugin可以建立index.html.open-browser-webpack-plugin 能在webpack加載的時候打開一個瀏覽器標籤頁

main.js

document.write('<h1>Hello World</h1>')
複製代碼

index.html不須要寫了哈哈哈哈

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'
    })
  ]
};
複製代碼

這個例子中能夠看到咱們不須要寫一個index.html 不須要咱們本身打開瀏覽器,webpack作好了

environment tag

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]
};
複製代碼

若是咱們使用下面這行代碼將環境變量設置爲true,能夠看到了日期

$ env DEBUG=true webpack-dev-server
複製代碼

代碼分割code spliting

相對於大型的app來講,全部的代碼放到一個單獨的文件會致使低效率的,webpack提供拆分紅塊的這種機制, 尤爲是在某些條件小纔會有需求的代碼塊,這些代碼塊應該在須要的時候加載,不須要的時候就不加載

使用require.ensure 來定義一個拆分點,用來告訴webpack 這個./a.js應該從bundle.js 中拆分,而且生成一個單獨的文件

main.js

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

a.js

module.exports = 'Hello World';
複製代碼

index.html

<html>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>
複製代碼

web.config.js

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

在運行的時候,其實webpack構建了兩個塊,bundle.js 和 1.bundle.js(來自a.js),只有在須要的時候加載1.bundle.js

bundle loader and code splitting

另外一種代碼拆分的方式是使用bundle-loader

在main.js 文件中

// 如今咱們須要a.js了,將會綁定在另外一個文件中
// 下面這句是告訴webpack 從別的塊中加載a.js 
var load = require('bundle-loader!./a.js');

// 等待a.js可用的時候,咱們就能獲取到這個exports
// 能夠使用異步來等待

load(function(file) {
  document.open();
  document.write('<h1>' + file + '</h1>');
  document.close();
});
複製代碼

common chunk

當多個script有公共的代碼塊時候, 咱們但願把這個抽取出來行成一個獨立的文件。咱們能夠使用commonschunkplugin來實現這個功能

例以下面的main1.jsx和main2.jsx

// 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')
  ]
}

複製代碼

三方代碼塊 vendor chunk

使用Commonschunkplugin還能夠實現吧script標籤內的三方庫抽取出造成一個單獨的文件

例如jQuery

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')
  ]
};
複製代碼

commonchunkplugin中有兩個參數,第一個是抽取出的塊的名字,第二個是抽取出以後的文件

若是想要讓某個模塊全局可用, 例如不使用require('jquery')卻能夠全局使用$和 jQuery, 能夠使用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"
    })
  ]
};
複製代碼

暴露全局變量

data.js

var data = 'Hello World';
複製代碼

使用externals來暴露全局變量 // 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'
  }
};
複製代碼

在externals屬性中data做爲全局變量在script中。

在main.jsx 中使用data:

var data = require('data');
var React = require('react');
var ReactDOM = require('react-dom');

ReactDOM.render(
  <h1>{data}</h1>,
  document.body
);
複製代碼
相關文章
相關標籤/搜索