一小時學會前端工程化

1、概要

1.一、前端工程化

隨着前端的不斷髮展與壯大,前端變得愈來愈複雜,組件化、模塊化、工程化、自動化成了前端發展中不可或缺的一部分,具體到前端工程化,面臨的問題是如何提升編碼->測試->維護階段的生產效率。css

前端工程化是使用軟件工程的技術和方法來進行前端項目的開發、維護和管理。html

前端工程化是依據業務特色,將前端開發的規範、流程、技術、工具、經驗等造成規範並創建成一種標準的體系。前端

如今的項目可能會不停的迭代,發佈就成了平常開發的一部分,前端不只要保證功能還要保證性能,傳統的一次次的發佈效率會很是低,前端工程化通常都有會藉助一些工具。vue

實現前端工程化的目的簡單來講就是經過流程規範、自動化工具來提高前端的開發效率、性能、質量、多人協做能力以及開發體驗,創建前端工程化是各個團隊必經的成長過程。node

1.1.一、前端工程化的任務

前端不只要保證功能還要考慮性能,要減小http請求數量、壓縮、合併、預處理、規範代碼、清理、打包、轉換等工做。react

前端大部分狀況下源代碼沒法直接運行,必須經過轉換後才能夠正常運行。構建就是作這件事情,把源代碼轉換成發佈到線上的可執行 JavaScrip、CSS、HTML 代碼,包括以下內容。jquery

(1)、代碼轉換:TypeScript 編譯成 JavaScript、SCSS 編譯成 CSS 等。webpack

(2)、文件優化:壓縮 JavaScript、CSS、HTML 代碼,壓縮合並圖片等。git

(3)、代碼分割:提取多個頁面的公共代碼、提取首屏不須要執行部分的代碼讓其異步加載。github

(4)、模塊合併:在採用模塊化的項目裏會有不少個模塊和文件,須要構建功能把模塊分類合併成一個文件。

(5)、自動刷新:監聽本地源代碼的變化,自動從新構建、刷新瀏覽器。

(6)、代碼校驗:在代碼被提交到倉庫前須要校驗代碼是否符合規範,以及單元測試是否經過。

(7)、自動發佈:更新完代碼後,自動構建出線上發佈代碼並傳輸給發佈系統。

構建實際上是工程化、自動化思想在前端開發中的體現,把一系列流程用代碼去實現,讓代碼自動化地執行這一系列複雜的流程。 構建給前端開發注入了更大的活力,解放了咱們的生產力。

1.二、前端工程化工具

歷史上前後出現一系列構建工具,它們各有其優缺點。因爲前端工程師很熟悉 JavaScript ,Node.js 又能夠勝任全部構建需求,因此大多數構建工具都是用 Node.js 開發的。

構建工具的主要功能就是實現自動化處理,例如對代碼進行檢查、預編譯、合併、壓縮;生成雪碧圖、sourceMap、版本管理;運行單元測試、監控等,固然有的工具還提供模塊化、組件化的開發流程功能。

 

若是把工具按類型分能夠分爲這三類:

(一)、基於任務運行的工具:Grunt、Gulp

它們會自動執行指定的任務,就像流水線,把資源放上去而後經過不一樣插件進行加工,它們包含活躍的社區,豐富的插件,能方便的打造各類工做流。

(二)、基於模塊化打包的工具:Browserify、Webpack、rollup.js

有過 Node.js 開發經歷的應該對模塊很熟悉,須要引用組件直接一個 require 就 OK,這類工具就是這個模式,還能夠實現按需加載、異步加載模塊。

(三)、整合型工具:Yeoman、FIS、jdf、Athena、cooking、weflow

使用了多種技術棧實現的腳手架工具,好處是即開即用,缺點就是它們約束了技術選型,而且學習成本相對較高。

1.2.一、Grunt

Grunt([ɡrʌnt]做呼嚕聲) 生態系統很是龐大,而且一直在增加。因爲擁有數量龐大的插件可供選擇,所以,你能夠利用 Grunt 自動完成許多事,而且花費不多的代價。若是找不到你所須要的插件,那就本身動手創造一個 Grunt 插件,而後將其發佈到 npm 上吧。

官網:https://gruntjs.com/

GitHub:https://github.com/gruntjs/

中文網:https://www.gruntjs.net/

對於須要反覆重複的任務,例如壓縮(minification)、編譯、單元測試、linting等,自動化工具能夠減輕你的勞動,簡化你的工做。當你在 Gruntfile 文件正確配置好了任務,任務運行器就會自動幫你或你的小組完成大部分無聊的工做。

Grunt 是老牌的構建工具,特色是配置驅動,你須要作的就是了解各類插件的功能,而後把配置整合到 Gruntfile.js 中,下面是配置例子:

複製代碼
module.exports = function(grunt) {
    grunt.initConfig({
        jshint: {
            files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
            options: {
                globals: {
                    jQuery: true
                }
            }
        },
        watch: {
            files: ['<%= jshint.files %>'],
            tasks: ['jshint']
        }
    });

    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-watch');

    grunt.registerTask('default', ['jshint']);
};
複製代碼

Grunt 缺點也是配置驅動,當任務很是多的狀況下,試圖用配置完成全部事簡直就是個災難;再就是它的 I/O 操做也是個弊病,它的每一次任務都須要從磁盤中讀取文件,處理完後再寫入到磁盤,例如:我想對多個 less 進行預編譯、壓縮操做,那麼 Grunt 的操做就是:

讀取 less 文件 -> 編譯成 css -> 存儲到磁盤 -> 讀取 css -> 壓縮處理 -> 存儲到磁盤

這樣一來當資源文件較多,任務較複雜的時候性能就是個問題了。

1.2.二、Gulp

Gulp(ɡʌlp狼吞虎嚥地吃,吞嚥)是一個基於流的自動化構建工具。 除了能夠管理和執行任務,還支持監聽文件、讀寫文件。

中文網:https://www.gulpjs.com.cn/

官網:https://gulpjs.com/

特色:

易於使用:經過代碼優於配置的策略,Gulp 讓簡單的任務簡單,複雜的任務可管理。

構建快速:利用 Node.js 流的威力,你能夠快速構建項目並減小頻繁的 IO 操做。

插件高質:Gulp 嚴格的插件指南確保插件如你指望的那樣簡潔高質得工做。

易於學習:經過最少的 API,掌握 Gulp 不太費力,構建工做盡在掌握:如同一系列流管道。

Gulp 被設計得很是簡單,只經過下面5種個方法就能夠勝任幾乎全部構建場景:

經過 gulp.task 註冊一個任務;

經過 gulp.run 執行任務;

經過 gulp.watch 監聽文件變化;

經過 gulp.src 讀取文件;

經過 gulp.dest 寫文件。

Gulp 的最大特色是引入了流的概念,同時提供了一系列經常使用的插件去處理流,流能夠在插件之間傳遞

Gulp 特色是代碼驅動,寫任務就和寫普通的 Node.js 代碼同樣:

複製代碼
var gulp = require('gulp');
var pug = require('gulp-pug');
var less = require('gulp-less');
var minifyCSS = require('gulp-csso');

gulp.task('html', function(){
    return gulp.src('client/templates/*.pug')
        .pipe(pug())
        .pipe(gulp.dest('build/html'))
});

gulp.task('css', function(){
    return gulp.src('client/templates/*.less')
        .pipe(less())
        .pipe(minifyCSS())
        .pipe(gulp.dest('build/css'))
});

gulp.task('default', [ 'html', 'css' ]);
複製代碼

再一個對文件讀取是流式操做(Stream),也就是說一次 I/O 能夠處理多個任務,仍是 less 的例子,Gulp 的流程就是:

讀取 less 文件 -> 編譯成 css -> 壓縮處理 -> 存儲到磁盤

Gulp 做爲任務類型的工具沒有明顯的缺點,惟一的問題可能就是完成相同的任務它須要寫的代碼更多一些,因此除非是項目有歷史包袱(原有項目就是基於 Grunt 構建)在 Grunt 與 Gulp 對比看來仍是比較推薦 Gulp!

適用場景:

經過上面的介紹能夠看出它們側重對整個過程的控制管理,實現簡單、對架構無要求、不改變開發模式,因此很是適合前端、小型、須要快速啓動的項目。

1.2.三、Yeoman

Yeoman([ˈjoʊmən]自耕農,自由民; 義勇騎兵隊成員,young+man)的目的不只是要爲新項目創建工做流,同時仍是爲了解決前端開發所面臨的諸多嚴重問題,例如零散的依賴關係。
Yeoman是Google的團隊和外部貢獻者團隊合做開發的,他的目標是經過Grunt(一個用於開發任務自動化的命令行工具)和Bower(一個HTML、CSS、Javascript和圖片等前端資源的包管理器)的包裝爲開發者建立一個易用的工做流。

Yeoman是一個強健的腳手架與構建工具,庫,及工做流程的組合,幫你網頁開發者快速建立出漂亮並且引人入勝的網頁程序,Yeoman幫助咱們建立項目,提供更好的工具來使咱們的項目更多樣化。

Yeoman提供generator系統,一個generator是一個插件,在咱們在一個完整的項目上使用‘yo’命令時,會運行該generator。經過這些官方的Generators,推出了Yeoman工做流,工做流是一個健壯、有本身特點的客戶端堆棧,包含能快速構建漂亮的網絡應用的工具和框架。Yeoman提供了負責開始項目開發的一切,沒有任何讓人頭痛的手動配置。

Yeoman主要提供了三個工具:腳手架(yo),構建工具(grunt),包管理器(bower)。這三個工具是分別獨立開發的,可是須要配合使用,來實現咱們更高效的工做流模式。

小結:

在 Npm Script 和 Grunt 時代,Web 開發要作的事情變多,流程複雜,自動化思想被引入,用於簡化流程;

在 Gulp 時代開始出現一些新語言用於提升開發效率,流式處理思想的出現是爲了簡化文件轉換的流程,例如將 ES6 轉換成 ES5。

在 Webpack 時代因爲單頁應用的流行,一個網頁的功能和實現代碼變得龐大,Web 開發向模塊化改進。

這些構建工具都有各自的定位和專一點,它們之間既能夠單獨地完成任務,也能夠相互搭配起來彌補各自的不足。 在瞭解這些常見的構建工具後,你須要根據本身的需求去判斷應該如何選擇和搭配它們才能更好地完成本身的需求。

通過多年的發展, Webpack 已經成爲構建工具中的首選,緣由是:

大多數團隊在開發新項目時會採用緊跟時代的技術,這些技術幾乎都會採用「模塊化+新語言+新框架」,Webpack 能夠爲這些新項目提供一站式的解決方案;

Webpack 有良好的生態鏈和維護團隊,能提供良好的開發體驗和保證質量;

Webpack 被全世界的大量 Web 開發者使用和驗證,能找到各個層面所需的教程和經驗分享。

1.三、WebPack

webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。

Webpack 是一個打包模塊化 JavaScript 的工具,在 Webpack 裏一切文件皆模塊,經過 Loader 轉換文件,經過 Plugin 注入鉤子,最後輸出由多個模塊組合成的文件。Webpack 專一於構建模塊化項目。

其官網的首頁圖很形象的畫出了 Webpack 是什麼,以下:

一切文件:JavaScript、CSS、SCSS、圖片、模板,在 Webpack 眼中都是一個個模塊,這樣的好處是能清晰的描述出各個模塊之間的依賴關係,以方便 Webpack 對模塊進行組合和打包。 通過 Webpack 的處理,最終會輸出瀏覽器能使用的靜態資源。

Webpack 具備很大的靈活性,能配置如何處理文件,大體使用以下:

複製代碼
module.exports = {
// 全部模塊的入口,Webpack 從入口開始遞歸解析出全部依賴的模塊
    entry: './app.js',
    output: {
// 把入口所依賴的全部模塊打包成一個文件 bundle.js 輸出 
        filename: 'bundle.js'
    }
}
複製代碼

1.3.一、Webpack的特色

把一切都視爲模塊:無論是 CSS、JS、Image 仍是 HTML 均可以互相引用,經過定義 entry.js,對全部依賴的文件進行跟蹤,將各個模塊經過 loader 和 plugins 處理,而後打包在一塊兒。

按需加載:打包過程當中 Webpack 經過 Code Splitting 功能將文件分爲多個 chunks,還能夠將重複的部分單獨提取出來做爲 commonChunk,從而實現按需加載。

優勢:

專一於處理模塊化的項目,能作到開箱即用一步到位;

經過 Plugin 擴展,完整好用又不失靈活;

使用場景不只限於 Web 開發;

社區龐大活躍,常常引入緊跟時代發展的新特性,能爲大多數場景找到已有的開源擴展;

良好的開發體驗。

缺點:

Webpack的缺點是隻能用於採用模塊化開發的項目。

上手比較難、對於新手而言須要經歷踩坑的過程。

對於Server 端渲染的多頁應用有點力不從心。

小結:

Webpack 特別適合配合 React.js、Vue.js 構建單頁面應用以及須要多人合做的大型項目,在規範流程都已約定好的狀況下每每能極大的提高開發效率與開發體驗。

1.3.二、資源

官網:https://webpack.js.org/

github:https://github.com/webpack/webpack

中文網:https://www.webpackjs.com/

深刻淺出webpack電子書:http://webpack.wuhaolin.cn/

1.3.三、工做流程

Webpack 是經過配置來實現管理,與 Grunt 不一樣的是它包含的許多自動化的黑盒操做因此配置起來會簡單不少(但遇到問題調試起來就很麻煩),一個典型的配置以下:

複製代碼
module.exports = {
    //插件項
    plugins: [commonsPlugin],
    //頁面入口文件配置
    entry: {
        index : './src/js/page/index.js'
    },
    //入口文件輸出配置
    output: {
        path: 'dist/js/page',
        filename: '[name].js'
    },
    module: {
        //加載器配置
        loaders: [
            { test: /\.css$/, loader: 'style-loader!css-loader' },
            { test: /\.js$/, loader: 'jsx-loader?harmony' },
            { test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
            { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
        ]
    },
    //其它解決方案配置
    resolve: {
        root: '/Users/Bell/github/flux-example/src', //絕對路徑
        extensions: ['', '.js', '.json', '.scss'],
        alias: {
            AppStore : 'js/stores/AppStores.js',
            ActionType : 'js/actions/ActionType.js',
            AppAction : 'js/actions/AppAction.js'
        }
    }
};
複製代碼

 

1.3.四、搭建WebPack開發環境

(1)、安裝NodeJS

在用 Webpack 執行構建任務時須要經過 webpack 可執行文件去啓動構建任務,因此須要安裝 webpack 可執行文件。 在安裝 Webpack 前請確保你的系統安裝了5.0.0及以上版本的 Node.js。

https://nodejs.org/下載安裝

設置國內npm的鏡像

$ npm install -g cnpm --registry=https://registry.npm.taobao.org

使用時用cnpm代替npm

(2)、安裝webpack

安裝 Webpack 到全局

安裝到全局後你能夠在任何地方共用一個 Webpack 可執行文件,而不用各個項目重複安裝,安裝方式以下:

npm i -g webpack

cli:

全部cli參數:

webpack-cli 3.1.2

Usage: webpack-cli [options]
       webpack-cli [options] --entry <entry> --output <output>
       webpack-cli [options] <entries...> --output <output>
       webpack-cli <command> [options]

For more information, see https://webpack.js.org/api/cli/.

Config options:
  --config               Path to the config file
                         [string] [default: webpack.config.js or webpackfile.js]
  --config-register, -r  Preload one or more modules before loading the webpack
                         configuration      [array] [default: module id or path]
  --config-name          Name of the config to use                      [string]
  --env                  Environment passed to the config, when it is a function
  --mode                 Enable production optimizations or development hints.
                                  [choices: "development", "production", "none"]

Basic options:
  --context    The base directory (absolute path!) for resolving the `entry`
               option. If `output.pathinfo` is set, the included pathinfo is
               shortened to this directory.
                                       [string] [default: The current directory]
  --entry      The entry point(s) of the compilation.                   [string]
  --watch, -w  Enter watch mode, which rebuilds on file change.        [boolean]
  --debug      Switch loaders to debug mode                            [boolean]
  --devtool    A developer tool to enhance debugging.                   [string]
  -d           shortcut for --debug --devtool eval-cheap-module-source-map
               --output-pathinfo                                       [boolean]
  -p           shortcut for --optimize-minimize --define
               process.env.NODE_ENV="production"                       [boolean]
  --progress   Print compilation progress in percentage                [boolean]

Module options:
  --module-bind       Bind an extension to a loader                     [string]
  --module-bind-post  Bind an extension to a post loader                [string]
  --module-bind-pre   Bind an extension to a pre loader                 [string]

Output options:
  --output, -o                  The output path and file for compilation assets
  --output-path                 The output directory as **absolute path**
                                (required).
                                       [string] [default: The current directory]
  --output-filename             Specifies the name of each output file on disk.
                                You must **not** specify an absolute path here!
                                The `output.path` option determines the location
                                on disk the files are written to, filename is
                                used solely for naming the individual files.
                                                   [string] [default: [name].js]
  --output-chunk-filename       The filename of non-entry chunks as relative
                                path inside the `output.path` directory.
       [string] [default: filename with [id] instead of [name] or [id] prefixed]
  --output-source-map-filename  The filename of the SourceMaps for the
                                JavaScript files. They are inside the
                                `output.path` directory.                [string]
  --output-public-path          The `publicPath` specifies the public URL
                                address of the output files when referenced in a
                                browser.                                [string]
  --output-jsonp-function       The JSONP function used by webpack for async
                                loading of chunks.                      [string]
  --output-pathinfo             Include comments with information about the
                                modules.                               [boolean]
  --output-library              Expose the exports of the entry point as library
                                                                        [string]
  --output-library-target       Type of library
         [string] [choices: "var", "assign", "this", "window", "self", "global",
      "commonjs", "commonjs2", "commonjs-module", "amd", "umd", "umd2", "jsonp"]

Advanced options:
  --records-input-path       Store compiler state to a json file.       [string]
  --records-output-path      Load compiler state from a json file.      [string]
  --records-path             Store/Load compiler state from/to a json file. This
                             will result in persistent ids of modules and
                             chunks. An absolute path is expected. `recordsPath`
                             is used for `recordsInputPath` and
                             `recordsOutputPath` if they left undefined.[string]
  --define                   Define any free var in the bundle          [string]
  --target                   Environment to build for                   [string]
  --cache                    Cache generated modules and chunks to improve
                             performance for multiple incremental builds.
                      [boolean] [default: It's enabled by default when watching]
  --watch-stdin, --stdin     Stop watching when stdin stream has ended [boolean]
  --watch-aggregate-timeout  Delay the rebuilt after the first change. Value is
                             a time in ms.                              [number]
  --watch-poll               Enable polling mode for watching           [string]
  --hot                      Enables Hot Module Replacement            [boolean]
  --prefetch                 Prefetch this request (Example: --prefetch
                             ./file.js)                                 [string]
  --provide                  Provide these modules as free vars in all modules
                             (Example: --provide jQuery=jquery)         [string]
  --labeled-modules          Enables labeled modules                   [boolean]
  --plugin                   Load this plugin                           [string]
  --bail                     Report the first error as a hard error instead of
                             tolerating it.            [boolean] [default: null]
  --profile                  Capture timing information for each module.
                                                       [boolean] [default: null]

Resolving options:
  --resolve-alias         Redirect module requests                      [string]
  --resolve-extensions    Redirect module requests                       [array]
  --resolve-loader-alias  Setup a loader alias for resolving            [string]

Optimizing options:
  --optimize-max-chunks      Try to keep the chunk count below a limit
  --optimize-min-chunk-size  Minimal size for the created chunk
  --optimize-minimize        Enable minimizing the output. Uses
                             optimization.minimizer.                   [boolean]

Stats options:
  --color, --colors               Enables/Disables colors on the console
                                           [boolean] [default: (supports-color)]
  --sort-modules-by               Sorts the modules list by property in module
                                                                        [string]
  --sort-chunks-by                Sorts the chunks list by property in chunk
                                                                        [string]
  --sort-assets-by                Sorts the assets list by property in asset
                                                                        [string]
  --hide-modules                  Hides info about modules             [boolean]
  --display-exclude               Exclude modules in the output         [string]
  --display-modules               Display even excluded modules in the output
                                                                       [boolean]
  --display-max-modules           Sets the maximum number of visible modules in
                                  output                                [number]
  --display-chunks                Display chunks in the output         [boolean]
  --display-entrypoints           Display entry points in the output   [boolean]
  --display-origins               Display origins of chunks in the output
                                                                       [boolean]
  --display-cached                Display also cached modules in the output
                                                                       [boolean]
  --display-cached-assets         Display also cached assets in the output
                                                                       [boolean]
  --display-reasons               Display reasons about module inclusion in the
                                  output                               [boolean]
  --display-depth                 Display distance from entry point for each
                                  module                               [boolean]
  --display-used-exports          Display information about used exports in
                                  modules (Tree Shaking)               [boolean]
  --display-provided-exports      Display information about exports provided
                                  from modules                         [boolean]
  --display-optimization-bailout  Display information about why optimization
                                  bailed out for modules               [boolean]
  --display-error-details         Display details about errors         [boolean]
  --display                       Select display preset
              [string] [choices: "", "verbose", "detailed", "normal", "minimal",
                                                          "errors-only", "none"]
  --verbose                       Show more details                    [boolean]
  --info-verbosity                Controls the output of lifecycle messaging
                                  e.g. Started watching files...
                 [string] [choices: "none", "info", "verbose"] [default: "info"]
  --build-delimiter               Display custom text after build output[string]

Options:
  --help, -h     Show help                                             [boolean]
  --version, -v  Show version number                                   [boolean]
  --silent       Prevent output from being displayed in stdout         [boolean]
  --json, -j     Prints the result as JSON.                            [boolean]
View Code

要安裝 Webpack 到本項目,可按照你的須要選擇如下任意命令運行:

複製代碼
# npm i -D 是 npm install --save-dev 的簡寫,是指安裝模塊並保存到 package.json 的 devDependencies
# 安裝最新穩定版
npm i -D webpack

# 安裝指定版本
npm i -D webpack@<version>

# 安裝最新體驗版本
npm i -D webpack@beta
複製代碼

2、快速上手

2.一、建立一個項目或目錄

建立一個空項目或一個空目錄,不必定須要使用IDE,這裏我使用WebStorm

2.二、初始化項目

npm init -y (-y直接跳過提問階段)

複製代碼
name - 包名.
version - 包的版本號。
description - 包的描述。
homepage - 包的官網URL。
author - 包的做者,它的值是你在https://npmjs.org網站的有效帳戶名,遵循「帳戶名<郵件>」的規則,例如:zhangsan <zhangsan@163.com>。
contributors - 包的其餘貢獻者。
dependencies / devDependencies - 生產/開發環境依賴包列表。它們將會被安裝在 node_module 目錄下。
repository - 包代碼的Repo信息,包括type和URL,type能夠是git或svn,URL則是包的Repo地址。
main - main 字段指定了程序的主入口文件,require('moduleName') 就會加載這個文件。這個字段的默認值是模塊根目錄下面的 index.js。
keywords - 關鍵字
複製代碼

package.json詳解

2.三、安裝webpack

webpack4須要安裝webpack-cli:

npm i webpack webpack-cli --save-dev

2.四、建立目錄與文件

src/bar.js

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash'

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ');
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

實現使用lodash的join 鏈接字符串,在網頁中輸出字符串

依賴lodash、npm安裝lodash,在bar.js中import lodash的join方法,輸出text

npm i lodash --save

src/index.js

複製代碼
//入口文件

//導入自定義好的模塊
import bar from './bar';
//調用
bar();
複製代碼

建立配置文件webpack.config.js

複製代碼
//webpack配置文件

//依賴node中的path模塊
const path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置
    entry:"./src/index.js",
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件
        filename: "bundle.js"
    }
};
複製代碼

path.resolve獲取文件的路徑,_dirname爲當前模塊的絕對路徑,詳細解釋以下:

path.resolve()
//做用:path.resolve() 該方法將一些的 路徑/路徑段 解析爲絕對路徑。
//語法:path.resolve( [from…],to )
//說明:將參數to位置的字符解析到一個絕對路徑裏,[from … ]爲選填項,路徑源;

用法:
var path = require("path")     //引入node的path模塊

path.resolve('/foo/bar', './baz')   // returns '/foo/bar/baz'
path.resolve('/foo/bar', 'baz')   // returns '/foo/bar/baz'
path.resolve('/foo/bar', '/baz')   // returns '/baz'
path.resolve('/foo/bar', '../baz')   // returns '/foo/baz'
path.resolve('home','/foo/bar', '../baz')   // returns '/foo/baz'
path.resolve('home','./foo/bar', '../baz')   // returns '/home/foo/baz'
path.resolve('home','foo/bar', '../baz')   // returns '/home/foo/baz'
//總結:從後向前,若字符以 / 開頭,不會拼接到前面的路徑;若以 ../ 開頭,拼接前面的路徑,且不含最後一節路徑;若以 ./ 開頭 或者沒有符號 則拼接前面路徑;

//另:path.resolve老是返回一個以相對於當前的工做目錄(working directory)的絕對路徑。
View Code

index.html

webpack建立dist文件在dist中生成打包文件,而後再index.html中引用index.js文件

複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello WebPack</title>
</head>
<body>
<h2>Hello WebPack</h2>
<script src="dist/bundle.js"></script>
</body>
</html>
複製代碼

2.五、使用webpack命令打包

能夠指定配置文件

webpack --config webpack.config.js

也可使用默認的配置文件

webpack

打包的結果:

!function(n){var t={};function r(e){if(t[e])return t[e].exports;var u=t[e]={i:e,l:!1,exports:{}};return n[e].call(u.exports,u,u.exports,r),u.l=!0,u.exports}r.m=n,r.c=t,r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{enumerable:!0,get:e})},r.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},r.t=function(n,t){if(1&t&&(n=r(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(r.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var u in n)r.d(e,u,function(t){return n[t]}.bind(null,u));return e},r.n=function(n){var t=n&&n.__esModule?function(){return n.default}:function(){return n};return r.d(t,"a",t),t},r.o=function(n,t){return Object.prototype.hasOwnProperty.call(n,t)},r.p="",r(r.s=3)}([function(n,t,r){(function(n,e){var u;
View Code

 bundle.js文件:

2.六、運行

3、核心概念與執行過程

本質上,webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關係圖(dependency graph),其中包含應用程序須要的每一個模塊,而後將全部這些模塊打包成一個或多個 bundle。

從 webpack v4.0.0 開始,能夠不用引入一個配置文件。然而,webpack 仍然仍是高度可配置的。在開始前你須要先理解幾個核心概念:

3.一、模塊(Module)

在Webpack裏一切皆模塊,一個模塊對應着一個文件。Webpack 會從配置的Entry開始遞歸找出全部依賴的模塊。

webpack把一切都視爲模塊,無論是 CSS、JS、Image 仍是 HTML 均可以互相引用。Node.js 從最一開始就支持模塊化編程。然而,在 web,模塊化的支持正緩慢到來。在 web 存在多種支持 JavaScript 模塊化的工具,這些工具各有優點和限制。webpack 基於從這些系統得到的經驗教訓,並將模塊的概念應用於項目中的任何文件。

什麼是 webpack 模塊

對比 Node.js 模塊,webpack 模塊可以以各類方式表達它們的依賴關係,幾個例子以下:

  1. ES2015 import 語句
  2. CommonJS require() 語句
  3. AMD define 和 require 語句
  4. css/sass/less 文件中的 @import 語句。
  5. 樣式(url(...))或 HTML 文件(<img src=...>)中的圖片連接(image url)

支持的模塊類型

webpack 經過 loader 能夠支持各類語言和預處理器編寫模塊。loader 描述了 webpack 如何處理 非 JavaScript(non-JavaScript) _模塊_,而且在 bundle 中引入這些依賴。 webpack 社區已經爲各類流行語言和語言處理器構建了 loader,包括:

  1. CoffeeScript
  2. TypeScript
  3. ESNext (Babel)
  4. Sass
  5. Less
  6. Stylus

3.二、入口(entry)

入口,Webpack 執行構建的第一步將從 Entry 開始,可抽象成輸入。

入口起點(entry point)指示 webpack 應該使用哪一個模塊,來做爲構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模塊和庫是入口起點(直接和間接)依賴的。

每一個依賴項隨即被處理,最後輸出到稱之爲 bundles 的文件中,咱們將在下一章節詳細討論這個過程。

能夠經過在 webpack 配置中配置 entry 屬性,來指定一個入口起點(或多個入口起點)。默認值爲 ./src。

接下來咱們看一個 entry 配置的最簡單例子:

複製代碼
webpack.config.js

module.exports = {
    entry: './path/to/my/entry/file.js'
};
複製代碼

根據應用程序的特定需求,能夠以多種方式配置 entry 屬性。

多入口與多出口:

複製代碼
{
  entry: {
    app: './src/app.js',
    search: './src/search.js'
  },
  output: {
    filename: '[name].js',
    path: __dirname + '/dist'
  }
}

// 寫入到硬盤:./dist/app.js, ./dist/search.js
複製代碼

經常使用的佔位:

  1. [hash]:模塊標識符(module identifier)的 hash
  2. [chunkhash]:chunk 內容的 hash
  3. [name]:模塊名稱,key的名稱,非文件名稱
  4. [id]:模塊標識符(module identifier)
  5. [query]:模塊的 query,例如,文件名 ? 後面的字符串

3.三、出口(output)

輸出結果,在 Webpack 通過一系列處理並得出最終想要的代碼後輸出結果。

output 屬性告訴 webpack 在哪裏輸出它所建立的 bundles,以及如何命名這些文件,默認值爲 ./dist。基本上,整個應用程序結構,都會被編譯到你指定的輸出路徑的文件夾中。你能夠經過在配置中指定一個 output 字段,來配置這些處理過程:

複製代碼
webpack.config.js

const path = require('path');

module.exports = {
    entry: './path/to/my/entry/file.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
    }
};
複製代碼

在上面的示例中,咱們經過 output.filename 和 output.path 屬性,來告訴 webpack bundle 的名稱,以及咱們想要 bundle 生成(emit)到哪裏。可能你想要了解在代碼最上面導入的 path 模塊是什麼,它是一個 Node.js 核心模塊,用於操做文件路徑。

示例:

3.四、模塊轉換器(loader)

模塊轉換器,用於把模塊原內容按照需求轉換成新內容。

loader 讓 webpack 可以去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能夠將全部類型的文件轉換爲 webpack 可以處理的有效模塊,而後你就能夠利用 webpack 的打包能力,對它們進行處理。

本質上,webpack loader 將全部類型的文件,轉換爲應用程序的依賴圖(和最終的 bundle)能夠直接引用的模塊。

注意,loader 可以 import 導入任何類型的模塊(例如 .css 文件),這是 webpack 特有的功能,其餘打包程序或任務執行器的可能並不支持。咱們認爲這種語言擴展是有很必要的,由於這可使開發人員建立出更準確的依賴關係圖。

在更高層面,在 webpack 的配置中 loader 有兩個目標:

  1. test 屬性,用於標識出應該被對應的 loader 進行轉換的某個或某些文件。
  2. use 屬性,表示進行轉換時,應該使用哪一個 loader。
複製代碼
webpack.config.js

const path = require('path');

const config = {
    output: {
        filename: 'my-first-webpack.bundle.js'
    },
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    }
};

module.exports = config;
複製代碼

以上配置中,對一個單獨的 module 對象定義了 rules 屬性,裏面包含兩個必須屬性:test 和 use。這告訴 webpack 編譯器(compiler) 以下信息:

「webpack 編譯器,當你碰到「在 require()/import 語句中被解析爲 '.txt' 的路徑」時,在你對它打包以前,先使用 raw-loader 轉換一下。」

3.五、插件(plugins)

擴展插件,在 Webpack 構建流程中的特定時機注入擴展邏輯來改變構建結果或作你想要的事情。

loader 被用於轉換某些類型的模塊,而插件則能夠用於執行範圍更廣的任務。插件的範圍包括,從打包優化和壓縮,一直到從新定義環境中的變量。插件接口功能極其強大,能夠用來處理各類各樣的任務。

想要使用一個插件,你只須要 require() 它,而後把它添加到 plugins 數組中。多數插件能夠經過選項(option)自定義。你也能夠在一個配置文件中由於不一樣目的而屢次使用同一個插件,這時須要經過使用 new 操做符來建立它的一個實例。

複製代碼
webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 經過 npm 安裝
const webpack = require('webpack'); // 用於訪問內置插件

const config = {
    module: {
        rules: [
            { test: /\.txt$/, use: 'raw-loader' }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({template: './src/index.html'})
    ]
};

module.exports = config;
複製代碼

3.六、模式(mode)

經過選擇 development 或 production 之中的一個,來設置 mode 參數,你能夠啓用相應模式下的 webpack 內置的優化

module.exports = {
    mode: 'production'
};

webpack4容許咱們指定編譯使用開發模式仍是生產模式,這由mode這個配置來控制,value爲枚舉值:development/production,分別對應開發模式和生產模式(這個配置能夠做爲命令行的配置參數也能夠做爲配置文件中的一個配置項,默認值是production,即生產模式)。

源碼仍是不支持調試(都用eval函數包住),指定編譯時的source-map生成方式,默認值是eval,能夠解決問題。

3.七、代碼塊(Chunk)

一個 Chunk 由多個模塊組合而成,用於代碼合併與分割。

3.八、WebPack執行過程

Webpack 啓動後會從 Entry 裏配置的 Module 開始遞歸解析 Entry 依賴的全部 Module。 每找到一個 Module, 就會根據配置的 Loader 去找出對應的轉換規則,對 Module 進行轉換後,再解析出當前 Module 依賴的 Module。 這些模塊會以 Entry 爲單位進行分組,一個 Entry 和其全部依賴的 Module 被分到一個組也就是一個 Chunk。最後 Webpack 會把全部 Chunk 轉換成文件輸出。 在整個流程中 Webpack 會在恰當的時機執行 Plugin 裏定義的邏輯。

Webpack從入口(entry)開始工做,一般這些是JavaScript模塊,其中webpack開始其遍歷過程。在此過程當中,webpack會根據加載器配置評估入口(entry)匹配,這些配置告訴webpack如何轉換每一個匹配。

入口(entry)自己就是一個模塊。當webpack遇到一個入口時,webpack會嘗試使用入口的resolve配置將入口與文件系統匹配。除了node_modules以外,咱們還能夠告訴webpack對特定目錄執行查找。也能夠調整webpack與文件擴展名匹配的方式,而且能夠爲目錄定義特定的別名。該耗竭與包章涵蓋了更詳細的這些想法。

若是解析經過失敗,webpack會引起運行時錯誤。若是webpack設法正確解析文件,webpack將根據加載器定義對匹配的文件執行處理。每一個加載器對模塊內容應用特定的轉換。

能夠經過多種方式配置加載程序與已解析文件匹配的方式,包括文件類型和文件系統中的位置。Webpack的靈活性甚至容許咱們根據文件導入項目的位置對文件應用特定的轉換。

對webpack的加載器執行相同的解析過程。Webpack容許咱們在肯定應使用哪一個加載器時應用相似的邏輯。因爲這個緣由,裝載程序已經解析了本身的配置。若是webpack沒法執行加載程序查找,則會引起運行時錯誤。

在實際應用中你可能會遇到各類奇怪複雜的場景,不知道從哪開始。 根據以上總結,你會對 Webpack 有一個總體的認識,這能讓你在之後使用 Webpack 的過程當中快速知道應該經過配置什麼去完成你想要的功能,而不是無從下手。

 下圖能夠簡易的描述出webpack打包過程,該過程主要分爲三個階段:module構建、trunk構建和產出三個階段:

4、模塊轉換器Loader

loader 用於對模塊的源代碼進行轉換。loader 可使你在 import 或"加載"模塊時預處理文件。所以,loader 相似於其餘構建工具中「任務(task)」,並提供了處理前端構建步驟的強大方法。loader 能夠將文件從不一樣的語言(如 TypeScript)轉換爲 JavaScript,或將內聯圖像轉換爲 data URL。loader 甚至容許你直接在 JavaScript 模塊中 import CSS文件!

loader 是對應用程序中資源文件進行轉換。它們是(運行在 Node.js 中的)函數,能夠將資源文件做爲參數的來源,而後返回新的資源文件。

 

4.一、loader特性

loader 支持鏈式傳遞。可以對資源使用流水線(pipeline)。一組鏈式的 loader 將按照相反的順序執行。loader 鏈中的第一個 loader 返回值給下一個 loader。在最後一個 loader,返回 webpack 所預期的 JavaScript。

  • loader 能夠是同步的,也能夠是異步的。
  • loader 運行在 Node.js 中,而且可以執行任何可能的操做。
  • loader 接收查詢參數。用於對 loader 傳遞配置。
  • loader 也可以使用 options 對象進行配置。

除了使用 package.json 常見的 main 屬性,還能夠將普通的 npm 模塊導出爲 loader,作法是在 package.json 裏定義一個 loader 字段。

插件(plugin)能夠爲 loader 帶來更多特性。

loader 可以產生額外的任意文件。

loader 經過(loader)預處理函數,爲 JavaScript 生態系統提供了更多能力。 用戶如今能夠更加靈活地引入細粒度邏輯,例如壓縮、打包、語言翻譯和其餘更多。

loader 遵循標準的模塊解析。多數狀況下,loader 將從模塊路徑(一般將模塊路徑認爲是 npm install, node_modules)解析。

loader 模塊須要導出爲一個函數,而且使用 Node.js 兼容的 JavaScript 編寫。一般使用 npm 進行管理,可是也能夠將自定義 loader 做爲應用程序中的文件。按照約定,loader 一般被命名爲 xxx-loader(例如 json-loader)。

4.二、使用loader的三種方式

(1)、配置(推薦):在 webpack.config.js 文件中指定 loader

module.rules 容許你在 webpack 配置中指定多個 loader。 這是展現 loader 的一種簡明方式,而且有助於使代碼變得簡潔。同時讓你對各個 loader 有個全局概覽:

複製代碼
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: true
            }
          }
        ]
      }
    ]
  }
複製代碼

Loaders須要單獨安裝而且須要在webpack.config.js中的modules關鍵字下進行配置,Loaders的配置包括如下幾方面:

複製代碼
test:一個用以匹配loaders所處理文件的拓展名的正則表達式(必須)

loader:loader的名稱(必須)

include/exclude:手動添加必須處理的文件(文件夾)或屏蔽不須要處理的文件(文件夾)(可選)

query:爲loaders提供額外的設置選項(可選)
複製代碼

(2)、內聯:在每一個 import 語句中顯式指定 loader

能夠在 import 語句或任何等效於 "import" 的方式中指定 loader。使用 ! 將資源中的 loader 分開。分開的每一個部分都相對於當前目錄解析。

import Styles from 'style-loader!css-loader?modules!./styles.css';

經過前置全部規則及使用 !,能夠對應覆蓋到配置中的任意 loader。

選項能夠傳遞查詢參數,例如 ?key=value&foo=bar,或者一個 JSON 對象,例如 ?{"key":"value","foo":"bar"}。

儘量使用 module.rules,由於這樣能夠減小源碼中的代碼量,而且能夠在出錯時,更快地調試和定位 loader 中的問題。

(3)、CLI:在 shell 命令中指定它們

你也能夠經過 CLI 使用 loader:

webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'

這會對 .jade 文件使用 jade-loader,對 .css 文件使用 style-loader 和 css-loader。

4.三、常見的loader

4.3.一、文件

  • raw-loader 加載文件原始內容(utf-8)
  • val-loader 將代碼做爲模塊執行,並將 exports 轉爲 JS 代碼
  • url-loader 像 file loader 同樣工做,但若是文件小於限制,能夠返回 data URL
  • file-loader 將文件發送到輸出文件夾,並返回(相對)URL

4.3.二、JSON

4.3.三、轉換編譯(Transpiling)

4.3.四、模板(Templating)

  • html-loader 導出 HTML 爲字符串,須要引用靜態資源
  • pug-loader 加載 Pug 模板並返回一個函數
  • jade-loader 加載 Jade 模板並返回一個函數
  • markdown-loader 將 Markdown 轉譯爲 HTML
  • react-markdown-loader 使用 markdown-parse parser(解析器) 將 Markdown 編譯爲 React 組件
  • posthtml-loader 使用 PostHTML 加載並轉換 HTML 文件
  • handlebars-loader 將 Handlebars 轉移爲 HTML
  • markup-inline-loader 將內聯的 SVG/MathML 文件轉換爲 HTML。在應用於圖標字體,或將 CSS 動畫應用於 SVG 時很是有用。

4.3.五、樣式

  • style-loader 將模塊的導出做爲樣式添加到 DOM 中
  • css-loader 解析 CSS 文件後,使用 import 加載,而且返回 CSS 代碼
  • less-loader 加載和轉譯 LESS 文件
  • sass-loader 加載和轉譯 SASS/SCSS 文件
  • postcss-loader 使用 PostCSS 加載和轉譯 CSS/SSS 文件
  • stylus-loader 加載和轉譯 Stylus 文件

4.3.六、清理和測試(Linting && Testing)

4.3.七、框架(Frameworks)

  • vue-loader 加載和轉譯 Vue 組件
  • polymer-loader 使用選擇預處理器(preprocessor)處理,而且 require() 相似一等模塊(first-class)的 Web 組件
  • angular2-template-loader 加載和轉譯 Angular 組件

4.四、raw-loader(文件原始內容轉換器)

一個能夠用於加載文件做爲字符串使用的加載器,使用UTF-8編碼。

安裝

npm i --D raw-loader

 安裝結果:

用法一:

經過 webpack 配置、命令行或者內聯使用 loader。

複製代碼
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.txt$/,
                use: 'raw-loader'
            }
        ]
    }
}
複製代碼

在你的項目中

import txt from './file.txt';

用法二:經過命令行(CLI)

webpack --module-bind 'txt=raw-loader'

用法三:在你的項目中

import txt from 'file.txt';

內聯使用

import txt from 'raw-loader!./file.txt';

示例:

webpack.config.json

//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {  //模塊處理
        rules: [ //處理器
            {
                test:/\.txt$/,  //當模塊的後綴爲.txt時匹配
                use: "raw-loader"  //模塊轉換器,能夠以對象的形式指定參數
            }
        ]
    },
    mode: "development"
};
View Code

src/file1.txt

A loader for webpack that lets you import files as a string.

src/bar.js

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

運行結果:

內聯使用模塊處理器:

4.五、CSS Loader(樣式處理)

webpack提供兩個工具處理樣式表,css-loader 和 style-loader,兩者處理的任務不一樣,css-loader使你可以使用相似@import 和 url(...)的方法實現 require()的功能,style-loader將全部的計算後的樣式加入頁面中,兩者組合在一塊兒使你可以把樣式表嵌入webpack打包後的JS文件中。

  • css-loader: 加載.css文件
  • style-loader:使用<style>將css-loader內部樣式注入到咱們的HTML頁面

css-loader詳解:

https://www.npmjs.com/package/css-loader

https://www.webpackjs.com/loaders/css-loader/

style-loader詳解:

https://www.npmjs.com/package/style-loader

https://www.webpackjs.com/loaders/style-loader/

4.5.一、安裝

//安裝
npm i style-loader css-loader -D

4.5.二、配置

複製代碼
const path = require("path");

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test:/\.css/,
                use:['style-loader',{
                    loader: 'css-loader',
                    options: {
                        sourceMap:true
                    }
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

4.5.三、定義樣式與引用

base.css

複製代碼
h2{
    height: 40px;
    line-height: 40px;
    background: crimson;
    color:#fff;
}
複製代碼

bar.js

複製代碼
import {join} from 'lodash';
import base from '../css/base.css';

export default function bar() {
    function component() {
        var element=document.createElement("h2");
        element.innerHTML=join(['Hello','Webpack!']);
        return element;
    }
    document.body.appendChild(component());
}
複製代碼

4.5.四、打包運行

打包:

運行:

生成代碼:

4.5.五、注意事項

  1. rules裏的數據類型爲對象,每個loader都是一個對象
  2. test表示loader要處理什麼類型的文件,這裏用了一個正則去匹配文件類型
  3. use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
  4. 這個loader的意思爲,在入口文件裏找到.css類型的文件,先拿css-loader去處理成瀏覽器認識的css,再拿style-loader把處理後的css放在頁面的style標籤裏

4.六、sass-loader(加載和轉譯 SASS/SCSS 文件)

加載sass或scss文件並轉譯成css

用css-loader或raw-loader 轉換成一個JS模塊或用ExtractTextPlugin插件將樣式分隔成一個單獨文件。

安裝

npm i sass-loader node-sass --D

 

node-sass 和 webpack 是 sass-loader 的 peerDependency,所以可以精確控制它們的版本。

示例

css/baseScss.scss

按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼

 

經過將 style-loader 和 css-loader 與 sass-loader 鏈式調用,能夠馬上將樣式做用在 DOM 元素。

配置webpack.config.json

複製代碼
//webpack配置文件

//依賴node中的path模塊
var path=require('path');

//定義一個默認模塊對象
module.exports={
    //指定入口文件的位置,多入口
    entry:{
        index:"./src/index.js",
        main:"./src/main.js"
    },
    //設置輸出結果
    output: {
        //路徑,將相對路徑轉絕對路徑
        path:path.resolve(__dirname,'dist'),
        //文件,[name]是模塊名稱,佔位
        filename: "[name].bundle.js"
    },
    module: {  //模塊處理
        rules: [ //處理器
            {
                test:/\.txt$/,  //當模塊的後綴爲.txt時匹配
                use: "raw-loader"  //模塊轉換器,能夠以對象的形式指定參數
            },
            {
                test:/\.css$/,  //匹配全部css模塊
                //use表示要使用哪一個loader,它的值是個數組,loader的使用順序是從後往前
                use: ["style-loader",{
                    loader: "css-loader",  //轉換器名稱
                    options: {  //配置選項
                        modules:true,  //模塊化
                        sourceMap:true  //是否生成調試文件
                    }
                }]  //使用多個模塊轉換器
            },
            {
                test: /\.scss$/,
                use: [{
                    loader: "style-loader" // 將 JS 字符串生成爲 style 節點
                }, {
                    loader: "css-loader" // 將 CSS 轉化成 CommonJS 模塊
                }, {
                    loader: "sass-loader" // 將 Scss 編譯成 CSS
                }]
            }
        ]
    },
    mode: "development"
};
複製代碼

 

導入scss做爲模塊

複製代碼
//定義模塊
//部分依賴lodash中的join方法
import {join} from 'lodash';
//導入模塊,得到file1.txt中的文件內容,被raw-loader處理
import message from './file1.txt';
//導入樣式文件
//import '../css/baseCss.css'
//導入預處理樣式文件
import '../css/baseScss.scss'

//導出一個默認模塊
export default function bar() {
    function component() {
        //建立DOM元素
        var element=document.createElement("h2");
        //使用join鏈接數組將結果寫入元素的html中
        element.innerHTML=join(['Hello','Webpack','!'],' ')+"<br/>"+message;
        return element;
    }
    //在body中添加子元素
    document.body.appendChild(component());
}
複製代碼

打包後運行結果:

一般,生產環境下比較推薦的作法是,使用 ExtractTextPlugin 將樣式表抽離成專門的單獨文件。這樣,樣式表將再也不依賴於 JavaScript:

複製代碼
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "[name].[contenthash].css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = {
    ...
        module
:
{
    rules: [{
        test: /\.scss$/,
        use: extractSass.extract({
            use: [{
                loader: "css-loader"
            }, {
                loader: "sass-loader"
            }],
// 在開發環境使用 style-loader
            fallback: "style-loader"
        })
    }]
}
,
plugins: [
    extractSass
]
}
;
複製代碼

 

4.七、url-loader(路徑處理器)

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

安裝

npm install --save-dev url-loader file-loader

用法

url-loader 功能相似於 file-loader,可是在文件大小(單位 byte)低於指定的限制時,能夠返回一個 DataURL。

import img from './image.png'

配置

複製代碼
webpack.config.js

module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|gif)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 8192
                        }
                    }
                ]
            }
        ]
    }
}
複製代碼

示例

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

5、插件plugins

 

5.一、單獨提取CSS

運行後,在dist目錄裏只有兩個文件,一個bundle.js一個index.html文件,並無css文件,同時打開index.html源碼後也沒有發現有css的內容。這是由於style-loader的做用,它把css一同打包到了js文件裏,js文件在能過DOM動態建立style標籤並添加到頁面裏。因此css的內容已經放到了index.bundle.js裏。

 這種形式只有當文件內容很少的時候可使用,若是CSS的內容以及JS的內容很是的多,把兩塊都打包到一個文件裏就會增長文件的體積,用戶打開頁面的時候下載速度會受影響,同時影響用戶體驗。這就須要把CSS文件單獨拎出來,那須要一個插件來配合loader才能完成

mini-css-extract-plugin

webpack版本須要4.3以上,低版本請使用extract-text-webpack-plugin

使用步驟:

一、安裝

npm i mini-css-extract-plugin -D

二、在webpack.config.js裏引入模塊

const MiniCssExtractPlugin=require("mini-css-extract-plugin");

三、寫入plugins

plugins:[
new HtmlWebpackPlugin({
title:'tom',
template:'./src/template.html',
filename:'index.html',
}),
new MiniCssExtractPlugin({
filename:'css/index.css' //文件目錄會放入output.path裏
}),
]

四、寫入loader

module:{
rules:[
{
test:/\.css$/,
use:[MiniCssExtractPlugin.loader,"css-loader"] //代替style-loader
}
]
}

執行命令npm run build後能夠看到dist目錄裏已經多了一個css文件夾,這個文件夾裏放了一個index.css文件。打開index.html源碼看到css文件已經經過link標籤引入,這些功能都是mini-css-extract-plugin所作的

相關文章
相關標籤/搜索