初學webpack與react

剛接觸webpack,在網上看了些入門的教程和資料,在此做下記錄。css

什麼是webpack?

簡單說就是模塊加載器,本文不做過多的介紹。html

安裝webpack

首先確保你的機器已經安裝了Node.js和npm(安裝方式請參考其餘相關資料)。
第一步,爲你的項目新建一個文件夾,而後輸入 npm init,而後填寫相關問題。
這樣會爲你建立了 package.json。
第二步,接下來咱們安裝 Webpack,咱們要把它安裝在本地,輸入 npm i webpack --save-dev
到此就完成了webpack的安裝了。node

項目目錄

  • /app
    main.js
    component.jsreact

  • /build
    bundle.js (自動建立)
    index.htmlwebpack

package.json
webpack.config.jsweb


咱們會使用 Webpack 在咱們的 /app 裏來自動建立 bundle.js 。接下來,咱們來設置 webpack.config.js。npm

設置webpack

webpack.config.js文件設置json

var path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'app/main.js'),
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
};

按上述項目目錄時,__dirname可寫爲''瀏覽器

運行一個HelloWorld demo

通過上述的配置,咱們已經有了一個最簡單的配置了,下面咱們用它來編譯一個簡單的Hello World。服務器

  • app/component.js

'use strict';

module.exports = function () {
    var element = document.createElement('h1');

    element.innerHTML = 'Hello world';

    return element;
};
  • app/main.js

'use strict';
var component = require('./component.js');

document.body.appendChild(component());

而後在你的命令行運行 webpack,接着你能夠看到應用會開始編譯,一個 bundle.js 文件會這樣出如今 /build 文件夾下。

  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

咱們在index.html中引入剛纔編譯好的bundle.js,咱們能夠打開 index.html,在瀏覽器中預覽一下效果。

設置 package.json scripts

npm是一個很是好用的用來編譯的指令,經過 npm 你能夠不用去擔憂項目中使用了什麼技術,你只要調用這個指令就能夠了,只要你在 package.json 中設置 scripts 的值就能夠了。
接下來咱們把編譯經過 npm run build 來執行:
把下面的內容添加到 package.json中。

"scripts": {
    "build": "webpack"
}

如今你能夠輸入 npm run build 就能夠編譯了。

開始工做流

每次編譯都須要輸入npm run build,想必你們都不肯意,下面咱們使用webpack-dev-server在每次文件改變後自動執行編譯。

設置webpack-dev-server

第一步須要安裝webpack-dev-server,在命令行中輸入 npm i webpack-dev-server --save,安裝完成後咱們須要調整package.jsonscripts 部分去包含這個指令。

  • package.json

{
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
  }
}

配置完成後,咱們能夠在命令行裏運行 npm run dev ,運行的時候他會執行 dev 屬性裏的值。編譯完成後,咱們能夠訪問"http://localhost:8080" 看到效果。
上述配置頂的意義:
一、webpack-dev-server - 在 localhost:8080 創建一個 Web 服務器
三、devtool eval - 爲你的代碼建立源地址。當有任何報錯的時候可讓你更加精確地定位到文件和行號
四、progress - 顯示合併代碼進度
五、colors - 命令行中顯示顏色!
六、content-base build - 指向設置的輸出目錄

讓瀏覽器自動刷新

當運行 webpack-dev-server 的時候,它會監聽你的文件修改。當項目從新合併以後,會通知瀏覽器刷新。爲了可以觸發這樣的行爲,你須要把你的 index.html 放到 build/ 文件夾下,而後作這樣的修改:

  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <script src="http://localhost:8080/webpack-dev-server.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

咱們須要增長一個腳本當發生改動的時候去自動刷新應用,你須要在配置中增長一個入口點。

var path = require('path');

module.exports = {
    entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
};

按上述目錄時,__dirname可設置爲''

就是這樣!如今你的應用就能夠在文件修改以後自動刷新了。

模塊

Webpack 容許你使用不一樣的模塊類型,可是 「底層」必須使用同一種實現。全部的模塊能夠直接在盒外運行。

ES6 模塊

import MyModule from './MyModule.js';

CommonJS

var MyModule = require('./MyModule.js');

AMD

define(['./MyModule.js'], function (MyModule) {
});

理解文件路徑

一個模塊須要用它的文件路徑來加載,看一下下面的這個結構:

--app
------modules
-----------MyModule.js
------main.js (entry point)
------utils.js

打開 main.js 而後能夠經過下面兩種方式引入 app/modules/MyModule.js

  • app/main.js

// ES6
import MyModule from './modules/MyModule.js';

// CommonJS
var MyModule = require('./modules/MyModule.js');

最開始的 ./ 是 「相對當前文件路徑」
讓咱們打開 MyModule.js 而後引入 app/utils:

  • app/modules/MyModule.js

// ES6 相對路徑
import utils from './../utils.js';

// ES6 絕對路徑
import utils from '/utils.js';

// CommonJS 相對路徑
var utils = require('./../utils.js');

// CommonJS 絕對路徑
var utils = require('/utils.js');

相對路徑是相對當前目錄。絕對路徑是相對入口文件,這個案例中是 main.js。

安裝ReactJs

在命令行在輸入npm install react --save

在代碼中使用 ReactJS

  • component.jsx

import React from 'react';

export default class Hello extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}
  • main.js

import React from 'react';
import Hello from './component.jsx';

main();

function main() {
    React.render(<Hello />, document.getElementById('app'));
}
  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <div id="app"></div>

    <script src="http://localhost:8080/webpack-dev-server.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

轉換 JSX

爲了可以使用 JSX 語法,你須要用 Webpack 來轉碼你的 JavaScript,這是加載器的工做,咱們可使用一個很好用也有不少功能的 Babel。

npm install babel-loader --save-dev

如今咱們須要去配置 Webpack 來使用加載器。

  • webpack.config.js

var path = require('path');
var config = {
  entry: ['webpack/hot/dev-server', path.resolve('', 'app/main.js')],
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/, // 用正則來匹配文件路徑,這段意思是匹配 js 或者 jsx
      loader: 'babel' // 加載模塊 "babel" 是 "babel-loader" 的縮寫
    }]
  }
};

module.exports = config;

在命令行中運行 npm run dev,而後刷新頁面就能夠看到修改。

優化重合並

你可能注意到在引入 React JS 到你的項目以後,給你的應用從新合併會花費太多的時間。在開發環境中,最理想的是編譯最多 200 到 800 毫秒的速度,取決於你在開發的應用。
在開發環境中使用壓縮文件
爲了避免讓 Webpack 去遍歷 React JS 及其依賴,你能夠在開發中重寫它的行爲。

  • webpack.config.js

var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');

config = {
    entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
    resolve: {
        alias: {
          'react': pathToReact
        }
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            loader: 'babel'
        }],
        noParse: [pathToReact]
    }    
};

module.exports = config;

咱們在配置中作了兩件事:
一、無論 「React」 是何時在代碼中引入的,它會去匹配壓縮後的 React JS 文件取代去 node_modules 中遍歷。
二、無論 Webpack 何時試圖是解析壓縮文件,咱們阻止它,告訴它那不是必須的。

加載CSS

Webpack容許像加載任何代碼同樣加載 CSS。你能夠選擇你所須要的方式,可是你能夠爲每一個組件把全部你的 CSS 加載到入口主文件中來作任何事情。
加載 CSS 須要 css-loader 和 style-loader,他們作兩件不一樣的事情,css-loader會遍歷 CSS 文件,而後找到 url() 表達式而後處理他們,style-loader 會把原來的 CSS 代碼插入頁面中的一個 style 標籤中。
安裝加載器
在命令行中輸入npm install css-loader style-loader --save-dev
安裝完畢後能夠將加載器配置到 Webpack.config.js 文件中。

  • webpack.config.js

var path = require('path');
var config = {
  entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.jsx$/,
      loader: 'jsx'
    }, {
      test: /\.css$/, // Only .css files
      loader: 'style!css' // Run both loaders
    }]
  }
};

module.exports = config;

加載 CSS 文件
加載一個 CSS 文件就和加載其餘文件同樣:

  • main.js

import './main.css';
// Other code
  • Component.jsx

import './Component.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return <h1>Hello world!</h1>
  }
});

將全部CSS合併成一個
在你的主入口文件中個,好比 app/main.js 你能夠爲整個項目加載全部的 CSS:

  • app/main.js

import './project-styles.css';
// 其餘 JS 代碼

CSS 就徹底包含在合併的應用中,不再須要從新下載。
若是你想發揮應用中多重入口文件的優點,你能夠在每一個入口點包含各自的 CSS:

  • app/main.js

import './style.css';
// 其餘 JS 代碼
  • app/entryA/main.js

import './style.css';
// 其餘 JS 代碼
  • app/entryB/main.js

import './style.css';
// 其餘 JS 代碼

你把你的模塊用文件夾分離,每一個文件夾有各自的 CSS 和 JavaScript 文件。再次,當應用發佈的時候,導入的 CSS 已經加載到每一個入口文件中。
具體的組件
你能夠根據這個策略爲每一個組件建立 CSS 文件,可讓組件名和 CSS 中的 class 使用一個命名空間,來避免一個組件中的一些 class 干擾到另一些組件的 class

  • app/components/MyComponent.css

.MyComponent-wrapper {
  background-color: #EEE;
}
  • app/components/MyComponent.jsx

import './MyComponent.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return (
      <div className="MyComponent-wrapper">
        <h1>Hello world</h1>
      </div>
    )
  }
});

使用內聯樣式取代 CSS 文件
在 「React Native」 中你再也不須要使用任何 CSS 文件,你只須要使用 style 屬性,能夠把你的 CSS 定義成一個對象,那樣就能夠根據你的項目從新來考略你的 CSS 策略。

  • app/components/MyComponent.jsx

import React from 'react';

var style = {
  backgroundColor: '#EEE'
};

export default React.createClass({
  render: function () {
    return (
      <div style={style}>
        <h1>Hello world</h1>
      </div>
    )
  }
});
相關文章
相關標籤/搜索