一個現代化的webpack工程初建

一 媒介

文章引見了一個現代化的項目的webpack4環境是什麼樣的。這裏只是引見了基本的功用,假如須要細緻的相干只是能夠去webpack官網去查閱。
代碼地點:github
環境特性:
1.運用了webpack-dev-middleware,在文件內容變動以後自動編譯;
2.運用了webpack-hot-middleware,在熱編譯以後會自動革新頁面變動的內容,而不是革新悉數頁面
3.運用了server.js文件來本身掌握啟動http效勞,後期能夠擴大簡樸的後端功用

文章將webpack的設置文件寫成了三份:公用部份文件、開闢環境文件、線上環境文件,詳細在文章中會有細緻的引見。

注重:文章引見很細緻,合適新手入門運用,請耐煩瀏覽。

二 正文

1.path相干內容

文檔:http://nodejs.cn/api/path.html
我們常常用到的就是path.resolve和path.join,那末我們就講一下二者的用法和區分:
相干文章:Difference between path.resolve and path.join invocation?

(1)path.join
path.join() 要領運用平台特定的分隔符把悉數給定的 path 片斷連接到一同,並規範化天生的途徑。

path.join('/a', '/b') // Outputs '/a/b'
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // outputs '/foo/bar/baz/asdf'

summary:path.join一般用到的是簡樸的將字符串舉行拼接。
(2)path.resolve
path.resolve() 要領會把一個途徑或途徑片斷的序列剖析為一個絕對途徑
給定的途徑的序列是從右往左被處置懲罰的,背面每一個 path 被順次剖析,直到組織完成一個絕對途徑(就會住手剖析)

比方,給定的途徑片斷的序列為:/foo、/bar、baz,則挪用 path.resolve(‘/foo’, ‘/bar’, ‘baz’) 會返回 /bar/baz。

假如處置懲罰完悉數給定的 path 片斷後還未天生一個絕對途徑,則當前事情目次會被用上。
天生的途徑是規範化后的,且末端的斜杠會被刪除,除非途徑被剖析為根目次。
長度為零的 path 片斷會被疏忽。
假如沒有傳入 path 片斷,則 path.resolve() 會返回當前事情目次的絕對途徑。
例子:

path.resolve('/foo/bar', './baz');
// 返回: '/foo/bar/baz'

path.resolve('/foo/bar', '/tmp/file/');
// 返回: '/tmp/file

(3)work directory 與 dirname
事情目次和文件目次並非一向相稱,我們以’./src/view/index.js’文件為例:
文件目次是牢固的,就是文件地點的目次:./src/view/index.js
事情目次是不確定的,檢察當前地點目次:pwd

假如你是在./src/view/ 下實行的index.js,那末就和文件途徑雷同./src/view/index.js
然則假如你在./src下實行的index.js,那事情途徑則是./src

2.從server.js談起

我們要曉得server.js都做了些什麼:

1.開啟一個http效勞器
2.運用熱編譯中間件,及時編譯修悛改的內容
3.運用熱替代,及時檢察最新的頁面UI
4.【擴大】能夠做一些後端的東西

代碼以下:

const http = require('http');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');

// 運用express啟用一個效勞器
const express = require('express');

// 援用開闢環境下的webpack設置文件
const config = require('./webpack.dev');
const app = express();
const webpackConfig = webpack(config);
const devMiddlewareCompiler = webpackDevMiddleware(webpackConfig,{
    publicPath:config.output.publicPath
});
const hotMiddlewareCompiler = webpackHotMiddleware(webpackConfig,{
    log: false,
    heartbeat: 2000,
 })

app.use(devMiddlewareCompiler);// 運用熱編譯中間件
app.use(hotMiddlewareCompiler);// 運用熱替代中間件

app.listen(8080,function(){
    console.log('Example app listening on port 8080!\n');
});

注重:為何要把熱編譯的功用放在node內里呢?假如援用wepack-dev-server會自動治理熱編譯,它的道理也照樣應用express開啟了一個小型效勞器,只不過我們看不到它。所以假如你要本身掌握,而且想簡樸輕易的在後端做點小東西,能夠完整運用上面的要領。假如是後端比較重就不發起這麼寫了,你須要開啟兩台效勞,經由過程代辦的體式格局模仿舉行前後端通訊了。

3.webpack common

webpack.common,js設置了無論是開闢照樣宣布都須要的東西,比方一些loader的轉譯,代碼的打包緊縮等。
詳細代碼以下:

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    app: './src/index.js' // 進口文件index.js
  },
  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'
           ]
      }
  ],
},
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin({
      title: 'Production'
    }),
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist'),
  }
};

下面講一講主要做了什麼事:

3-1 file-loader

a. 加載圖片
假如我們要想像援用模塊那樣援用一個圖片,比方:

import Rose from './img/rose.jpg'

在 webpack 里擔任圖片翻譯的是 file-loader。而且,webpack 在終究構建時,會自動將模塊中援用的圖片拷貝到響應目次。假如你搜檢此元素,你將看到現實的文件名已變動為像 5c999da72346a995e7e2718865d019c8.png 一樣。這意味着 webpack 在 src 文件夾中找到我們的文件,並勝利處置懲罰過它!

b. 加載字體
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;
 }

【擴大】file-loader與url-loader
假如我們願望在頁面引入圖片(包括img的src和background的url)。當我們基於webpack舉行開闢時,引入圖片會碰到一些題目。个中一個就是援用途徑的題目。拿background款式用url引入背景圖來講,我們都曉得,webpack終究會將各個模塊打包成一個文件,因而我們款式中的url途徑是相對進口html頁面的,而不是相關於原始css文件地點的途徑的。這就會致使圖片引入失利。這個題目是用file-loader處理的,file-loader能夠剖析項目中的url引入(不僅限於css),依據我們的設置,將圖片拷貝到響應的途徑,再依據我們的設置,修正打包後文件援用途徑,使之指向準確的文件。別的,假如圖片較多,會發許多http要求,會下降頁面機能。這個題目能夠經由過程url-loader處理。url-loader會將引入的圖片編碼,天生dataURl。相當於把圖片數據翻譯成一串字符。再把這串字符打包到文件中,終究只須要引入這個文件就可以接見圖片了。固然,假如圖片較大,編碼會斲喪機能。因而url-loader供應了一個limit參數,小於limit字節的文件會被轉為DataURl,大於limit的還會運用file-loader舉行copy。

//url-loader封裝了file-loader。url-loader不依賴於file-loader,即運用url-loader時,只須要裝置url-loader即可
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192
            }
          }
        ]
      }
    ]
  }
}

3-2 css loader與style-loader
假如你在JS中運用:

import './index.css'

我們須要 CSS 加載器:

(1) css-loader – 預處置懲罰 CSS 文件
(2) style-loader – 將 CSS 插進去到 DOM 中的 style 標籤

要檢察 webpack 做了什麼,請搜檢頁面(不要檢察頁面源代碼,由於它不會顯現效果),並檢察頁面的 head 標籤。它應當包括我們在 index.js 中導入的 style 塊元素:<style>內容</style>。

注重:
(1)加載器的遞次是從后往前的,loader 的遞次很主要:假如把 style-loader 放到 css-loader 背面,我們就會撞見毛病。
(2)我們假如只運用了 css-loader,則 webpack 只是將 CSS 文件預處置懲罰成模塊然後打包到構建文件中,並不會插進去到頁面。

【擴大】將CSS零丁打包:
webpack1/2/3:extract-text-webpack-plugin
webpack4:mini-css-extract-plugin

3-3 htm-lwebpack-plugin
細緻引見見:html-webpack-plugin npm
這是一個webpack插件,能夠簡化建立HTML文件以便為webpack包供應效勞。 這關於webpack包來講迥殊有效,它在文件名中包括一個hash,用於變動每一個編譯。 你能夠讓插件為你天生一個HTML文件,運用lodash模板供應你本身的模板或運用你本身的加載器。

3-4 clean-webpack-plugin
細緻引見見:clean-wenpack-plugin
一個在建立之前消滅你build文件夾的webpack插件。在打包天生新的build文件的時刻消滅之前天生的,這異常有效。

4.webpack development

兩種環境的設置在webpack4中都支撐mode的設置:development/production,詳細的默許設置查詢能夠移步這裏:webpack4 Mode的默許設置

webpack.dev.config.js:

 const webpack = require('webpack');
 const merge = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
    mode:'development',
    plugins:[
      new webpack.NamedModulesPlugin(),
      new webpack.HotModuleReplacementPlugin(),
   ]
 });

這裏做了兩件事:
(1)mode:’development’:定義環境為開闢環境。在webpack4以後省了許多操縱,只須要指定為開闢環境,就會自動設定source map等信息
(2)HotModuleReplacementPlugin:模塊熱替代
運用熱替代須要兩步:

起首: Add the following plugins to the plugins array


plugins: [
    // OccurenceOrderPlugin is needed for webpack 1.x only
    new webpack.optimize.OccurenceOrderPlugin(),
    new webpack.HotModuleReplacementPlugin(),
    // Use NoErrorsPlugin for webpack 1.x
    new webpack.NoEmitOnErrorsPlugin()
]
Occurence ensures consistent build hashes, hot module replacement is somewhat self-explanatory, no errors is used to handle errors more cleanly.

其次:Add ‘webpack-hot-middleware/client’ into the entry array.

This connects to the server to receive notifications when the bundle rebuilds and then updates your client bundle accordingly.

5.webpack production

兩種環境的設置在webpack4中都支撐mode的設置:development/production,詳細的默許設置查詢能夠移步這裏:webpack4 Mode的默許設置

 const webpack = require('webpack');
 const path = require('path');
 const merge = require('webpack-merge');
//  const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
 const common = require('./webpack.common.js');


 module.exports = merge(common, {
     output:{
        // publicPath:path.resolve(__dirname, 'dist'),
     },
     mode:'production',
 });

指定環境為臨盆環境,默許開啟UglifyJSPlugin。

【擴大】將文件標記為無副作用(side-effect-free)
src/math.js:

export function square(x) {
  return x * x;
}

export function cube(x) {
  return x * x * x;
}

src/index.js:

import { cube } from './math.js';

math.js文件的square函數沒有被導入,然則,它依然被包括在 bundle 中。
在一個地道的 ESM 模塊天下中,識別出哪些文件有副作用很簡樸。但是,我們的項目沒法到達這類純度,所以,此時有必要向 webpack 的 compiler 供應提醒哪些代碼是“地道部份”。
這類體式格局是經由過程 package.json 的 “sideEffects” 屬性來完成的。

{
  "name": "your-project",
  "sideEffects": false
}

犹如上面提到的,假如一切代碼都不包括副作用,我們就可以夠簡樸地將該屬性標記為 false,來示知 webpack,它能夠安全地刪除未用到的 export 導出。
假如你的代碼確切有一些副作用,那末能夠改成供應一個數組:

{
  "name": "your-project",
  "sideEffects": [
    "./src/some-side-effectful-file.js"
  ]
}

三 跋文

    原文作者:specialCoder
    原文地址: https://segmentfault.com/a/1190000015323133
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞