整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Webpack 模塊化開發與配置

          Webpack 模塊化開發與配置

          ebpack 模塊化的配置,包括處理 js轉換 / css / html / eslint / 圖片等的 loader、plugin 配置。 傳說中前端配置工程師的基本修養……

          一 模塊(Module)

          模塊是為了完成某種功能所需的程序或子程序,模塊是系統中職責單一且可替換的部分。

          模塊化就是把系統代碼分為一系列職責單一且可替換的模塊。模塊化開發是指如何開發新的模塊和復用已有的模塊來實現應用的功能。

          javascript 的三大主流模塊規范已在上篇介紹過,這么不多贅述。

          Webpack 中一切皆模塊,包括 javascript、css、html、圖片、字體、富媒體及 less、sass、 各種 javascript 庫等等,webpack 可以針對不同的模塊用不同的 loader 做不同的解析編譯,做到按需加載。比如對于 less 代碼,可以先用 less-loader 轉換為 css 代碼,用 css-loader 處理其中的 url/import 等邏輯,最后用 style-loader 把 css 插入到 <style> 標簽里。

          1. Webpack對模塊的增強:import() 和神奇注釋(Magic Comments)

          Webpack 導入模塊的方式不限于三大主流模塊規范,提供了 import() 引入模塊的方式。

          與 import from 不同的是, import from 是靜態分析打包的,而 import() 是動態分析打包的,通過異步的方式加載模塊,import() 返回一個 Promise 對象。并且 import() 被視為分割點,被請求的模塊和它引用的所有子模塊,打包后會分割到一個單獨的 chunk 中。

          // 想象我們有一個從 cookies 或其他存儲中獲取語言的方法
          const language=detectVisitorLanguage();
          import(`./locale/${language}.json`).then((module)=> {
            // do something with the translations
          });

          神奇注釋(Magic Comments),是指可以通過在 import() 中添加注釋實現對打包的文件做一定的操作,比如給 chunk 命名、選擇不同模式。

          // 單個目標
          import(
            /* webpackChunkName: "my-chunk-name" */
            /* webpackMode: "lazy" */
            /* webpackExports: ["default", "named"] */
            'module'
          );
          
          // 多個可能的目標
          import(
            /* webpackInclude: /\.json$/ */
            /* webpackExclude: /\.noimport\.json$/ */
            /* webpackChunkName: "my-chunk-name" */
            /* webpackMode: "lazy" */
            /* webpackPrefetch: true */
            /* webpackPreload: true */
            `./locale/${language}`
          );
          

          Magic Comments

          說明

          webpackChunkName

          chunk 文件的名稱

          webpackInclude

          在導入解析過程中,用于匹配的正則表達式,只有匹配到的模塊才會被打包

          webpackExclude

          用于匹配的正則表達式,匹配到的模塊不會被打包

          webpackMode

          指定以不同的模式解析動態導入,可選值lazy/lazy-once/eager/weak

          webpackPrefetch

          是否預取模塊,及其優先級

          webpackPreload

          是否預加載模塊,及其優先級

          通過神奇注釋,import()不再是簡單的 JavaScript 異步加載器,還是任意模塊資源的加載器,舉例說明:如果我們頁面用到的圖片都放在src/assets/img文件夾下,你們可以通過下面方式將用到的圖片打包到一起:

          import(/* webpackChunkName: "image", webpackInclude: /\.(png|jpg|gif)/ */ './assets/img');
          

          2. Webpack對模塊的增強:require

          require.context()

          require.context(directory, includeSubdirs, filter)可以批量將 directory內的文件全部引入進文件,并且返回一個具有resolve的 context 對象,使用context.resolve(moduleId)則返回對應的模塊。該功能十分有用。

          • directory:目錄 string;
          • includeSubdirs:是否包含子目錄,可選,默認值是 true;
          • filter:過濾正則規則,可選項。

          require.context() 會將所有的文件都引入進 bundle。

          require.resolve()

          require.resolve(dependency: String)可以獲取模塊的唯一 ID, 并把模塊真實引入 bundle。

          require.include()

          require.include(dependency: String)引入一個不需要執行的 dependency,這樣可以用于優化輸出 chunk 中依賴模塊的位置。

          /**
           * 輸出:
          * entry chunk: file.js and a
          * anonymous chunk: b
          * anonymous chunk: c
          * 不使用 require.include('a'),輸出的兩個匿名 chunk 都會有模塊 a
          */
          require.include('a');
          require.ensure(['a', 'b'], function (require) {
            /* ... */
          });
          require.ensure(['a', 'c'], function (require) {
            /* ... */
          });
          

          二 使用 Babel 轉換 js 代碼

          在 webpack 中編寫 JavaScript 代碼,可以使用最新的 ES 語法,而最終打包的時候,webpack 會借助 Babel 將 ES6+語法轉換成在目標瀏覽器可執行 ES5 語法。

          Babel 擁有自己的 cli,可以單獨安裝使用,具體參考 Babel 官網,這里不贅述。

          在 npm 項目中,Babel 支持兩種文件配置方式:

          • 在 package.json 中配置 babel 屬性
          • 在項目根目錄下單獨創建 .babelrc 或者 .babelrc.js 文件
          // package.json
          {
              "name": "my-package",
              "version": "1.0.0",
              "babel": {
                  "presets": ["@babel/preset-env"]
              }
          }
          // .babelrc
          {
              "presets": ["@babel/preset-env"]
          }
          

          如果使用了webpack,也可以配置在 webpack 的配置文件中:

          // 安裝開發依賴
          npm i webpack babel-loader webpack-cli @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
          // 將 runtime 作為依賴
          npm i @babel/runtime -S
          
          // 配置示例
          module.exports={
              entry: './babel.js',
              mode: 'development',
              devtool: false,
              module: {
                  rules: [
                      {
                          test: /\.js$/,
                          use: [
                              {
                                  loader: 'babel-loader',
                                  options: {
                                      presets: [
                                          [
                                              '@babel/preset-env',
                                              {
                                                  useBuiltIns: 'usage'
                                              }
                                          ]
                                      ]
                                  }
                              }
                          ]
                      }
                  ]
              }
          };
          

          1. env 選項

          配置 env 選項可以實現在不同環境下使用不同的 Babel 配置。

          env 選項的值將從 process.env.BABEL_ENV 獲取,如果沒有的話,則獲取 process.env.NODE_ENV 的值,如果這個也沒有,會默認設置為 "development"。

          {
            "env": {
              "production": {
                "presets": ["@babel/preset-env"]
              }
            }
          }
          

          2. Polyfill

          polyfill:在 JavaScript 中表示一些可以抹平瀏覽器實現差異的代碼,比如某瀏覽器不支持 Promise,可以引入es6-promise-polyfill 等庫來解決。

          Babel 的插件分為兩類:轉換插件和語法解析插件。轉換插件用于對語法進行轉換,如 ES6 轉換為 ES5,語法解析插件用來擴展語法,如解析 React 特殊設計的jsx語法。對于各種情況下的語法轉換與解析,需要一個一個的引入相應的插件,這種方式比較麻煩,一般場景下,可以直接使用官方推出的插件組合@babel/preset-env。

          @babel/preset-env可以根據開發者的配置按需加載對應的插件,還可以根據代碼執行平臺環境和具體瀏覽器版本生成相應的 js 代碼。

          @babel/preset-env有兩個重要的配置項:useBuiltIns和target。

          /**
           * useBuiltIns: usage|entry|false,一般采用 usage 這種方式,即指定按需加載。
           * target: 指定構建目標
           */
          {
            "presets": [
              ["@babel/preset-env", {
                "useBuiltIns": "usage|entry|false"
                "targets": {
                    // "browsers": "IE 10" // 指定IE 10瀏覽器
                    "node": "8.9.3" // 如果在node環境中,指定node版本號
                }
              }]
            ]
          }
          

          Browserslist 目標瀏覽器的設置

          項目的實際開發與運行中,很多情況下要做一定的瀏覽器兼容,而 Browserslist 就是用來設置目標瀏覽器的工具。許多開發工具包括 npm、babel 都兼容內置了 Browserslist。

          Browserslist 的配置可以放在 package.json 中,也可以單獨放在配置文件.browserslistrc 中。相關的開發工具都會主動查找 browserslist 的配置文件,根據 browserslist 配置找出對應的目標瀏覽器集合。

          // package.json 內配置
          {
              "browserslist": ["last 2 version", "> 1%", "maintained node versions", "not ie < 11"]
          }
          // 兼顧不同環境的配置,設置BROWSERSLIST_ENV 或者 NODE_ENV可以配置不同的環境變量
          {
              "browserslist": {
                  "production": ["> 1%", "ie 10"],
                  "development": ["last 1 chrome version", "last 1 firefox version"]
              }
          }
          // 項目的根目錄下.browerslistrc文件:
          // 注釋是這樣寫的,以#號開頭
          // 每行一個瀏覽器集合描述
          last 2 version
          > 1%
          maintained node versions
          not ie < 11
          
          // 兼顧不同環境的配置
          [production staging]
          > 1%
          ie 10
          
          [development]
          last 1 chrome version
          last 1 firefox version
          

          常見的瀏覽器集合范圍說明:

          范圍

          說明

          last 2 versions

          caniuse.com網站跟蹤的最新兩個版本,假如 iOS 12 是最新版本,那么向后兼容兩個版本就是 iOS 11 和 iOS 12

          > 1%

          全球超過 1%人使用的瀏覽器,類似> 5% in US則指代美國 5%以上用戶

          cover 99.5%

          覆蓋 99.5%主流瀏覽器

          chrome > 50 ie 6-8

          指定某個瀏覽器版本范圍

          unreleased versions

          說有瀏覽器的 beta 版本

          not ie < 11

          排除 ie11 以下版本不兼容

          since 2013 last 2 years

          某時間范圍發布的所有瀏覽器版本

          maintained node versions

          所有被 node 基金會維護的 node 版本

          current node

          當前環境的 node 版本

          dead

          通過last 2 versions篩選的瀏覽器中,全球使用率低于0.5%且官方聲明不在維護或者事實上已經兩年沒有再更新的版本

          defaults

          默認配置,> 0.5% last 2 versions Firefox ESR not dead

          瀏覽器名稱列表(大小寫不敏感):

          瀏覽器

          說明

          瀏覽器

          說明

          Chrome

          chrome瀏覽器

          ChromeAndroid/and_chr

          chrome 安卓移動瀏覽器

          Edge

          Edge瀏覽器

          Explorer/ie

          ie瀏覽器

          Android

          安卓webview瀏覽器

          Baidu

          百度瀏覽器

          Firefox/ff

          火狐瀏覽器

          FirefoxAndroid/and_ff

          火狐安卓瀏覽器

          iOS/ios_saf

          iOS Safari 瀏覽器

          ExplorerMobile/ie_mob

          ie 移動瀏覽器

          Safari

          桌面版本 Safari

          Node

          nodejs

          Opera

          opera瀏覽器

          OperaMobile/op_mob

          opera 移動瀏覽器

          OperaMini/op_mini

          operaMini 瀏覽器

          QQAndroid/and_qq

          QQ 安卓瀏覽器

          Samsung

          三星瀏覽器

          UCAndroid/and_uc

          UC 安卓瀏覽器

          Electron

          Electron

          BlackBerry / bb

          黑莓瀏覽器

          Babel Polyfill 的最佳實踐:

          useBuiltIns:'usage'可以近乎完美的解決我們的 Polyfill 問題,它是按需引入模塊,根據 .browserslist + 業務實際代碼來設置引入 Polyfill,不會多余的引入。

          三 樣式相關配置

          Webpack 中一切皆模塊,經 loader 處理后的 CSS 可以在 js 中被直接引用。

          1. css-loader 與 style-loader

          // 引入 css-loader
          npm install --save-dev css-loader
          
          // webpack.config.js 配置loader
          {
              module: {
                  rules: [
                      {
                          test: /\.css$/,
                          use: ['css-loader']
                      }
                  ];
              }
          }
          
          // 代碼中引入 css 模塊
          import css from './css/index.css';
          console.log(css);
          
          // 或者不用webpack配置文件,直接在引入語句中使用loader
          import css from 'css-loader!./css/index.css';
          console.log(css);
          

          經 css-loader 處理后,css 模塊被打包轉換成 js 對象,可直接用 js 語法使用。

          style-loader 的作用是將 css-loader 打包好的 css 代碼以<style>標簽的形式插入到 html 文件中,一般情況下,在一個項目中 style-loader 與 css-loader 是成對出現的,并且 style-loader 要在 css-loader 之后。

          npm install --save-dev style-loader

          2. mini-css-extract-plugin

          CSS 作為<style>標簽放到 HTML 內還是不夠的,我們還需要將 CSS 以 <link> 的方式通過 URL 的方式引入進來,這時候就需要使用 mini-css-extract-plugin 。

          npm install --save-dev mini-css-extract-plugin
          const MiniCssExtractPlugin=require('mini-css-extract-plugin');
          module.exports={
              plugins: [
                  // 添加 plugin
                  new MiniCssExtractPlugin({
                      filename: '[name].css',
                      chunkFilename: '[id].css'
                  })
              ],
              module: {
                  rules: [
                      {
                          test: /\.css$/,
                          // 添加 loader
                          use: [MiniCssExtractPlugin.loader, 'css-loader']
                      }
                  ]
              }
          };
          

          3. CSS Modules

          CSS Modules 指的是所有的 CSS 類名及其動畫名都只是局部作用域的 CSS 文件。CSS Modules 主要解決的問題有:

          • 解決 CSS 類都是全局的,容易造成全局污染(樣式沖突);
          • JS 和 CSS 共享類名;
          • 可以方便的編寫出更加健壯和擴展方便的 CSS。

          CSS Module 的表現形式:

          /* app.css */
          .element {
              background-color: blue;
              color: white;
              font-size: 24px;
          }
          /* app.js */
          // 引入 app.css
          import styles from './app.css';
          // js 直接使用 CSS 的類名作為對象值
          let element=`
            <div class="${styles.element}">
              <p>CSS Modules</p>
            </div>
          `;
          document.write(element);
          

          CSS Modules 在 webpack.config.js 中的配置:

          // CSS Modules 相關的配置還有很多,可以查看css-loader對應的文檔。
          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.css$/,
                          use: [
                              'style-loader',
                              {
                                  loader: 'css-loader',
                                  options: {
                                      modules: true
                                  }
                              }
                          ]
                      }
                  ]
              }
          };
          

          4. CSS 預處理器

          常見的 CSS 預處理器有 Less、Sass 及其語法變種 Scss和Stylus。預處理器為 CSS 提供了變量、函數、運算、作用域、繼承、嵌套等語法,使其功能更加強大。

          以 less-loader 為例,less-loader 將 Less 語法編譯成 CSS,后續還需要使用 css-loader 和 style-loader 處理才可以,所以一般來說需要配合使用:

          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.less$/,
                          use: [
                              'style-loader',
                              {
                                  loader: 'css-loader',
                                  options: {
                                      modules: true
                                  }
                              },
                              'less-loader' // 將 Less 編譯為 CSS
                          ]
                      }
                  ]
              }
          };
          

          一些預處理語言需要安裝對應的解析器,例如 sass-loader,需要同時安裝 node-sass。

          npm install sass-loader node-sass --save-dev

          5. PostCSS:CSS 后處理器

          表現形式:

          /*沒有前綴的寫法*/
          .flex {
              display: flex;
          }
          
          /*經過 postcss autoprefixer 處理后*/
          .flex {
              display: -webkit-box;
              display: -webkit-flex;
              display: -ms-flexbox;
              display: flex;
          }
          

          PostCss 能實現的功能很多,除了添加前綴,還可以最新語法轉義、壓縮等,甚至可以擴展 CSS 的語言特性。配置了 postcss-loader 之后,WebPack 就可以使用 PostCSS 來處理 CSS了,但是 PostCSS 本身只不過是將 CSS 解析成 AST ,真正起作用的還需要依賴其強大的插件系統。

          PostCSS 配置其實主要是配置其使用哪些插件,PostCSS 的配置寫法有以下三種方式:

          • 通過配置文件postcss.config.js,一般放置在項目的根目錄下;
          • 通過 loader 的配置項 options;
          • 直接在 package.json 中添加個 postcss 屬性。
          /* postcss.config.js */
          // 引入postcss 插件
          const autoprefixer=require('autoprefixer');
          module.exports={
              plugins: [autoprefixer(['IE 10'])]
          };
          
          /* webpack.config.js */
          // 引入postcss 插件
          const autoprefixer=require('autoprefixer');
          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.css$/,
                          use: [
                              'style-loader',
                              'css-loader',
                              {
                                  loader: 'postcss-loader',
                                  options: {
                                      // 通過 plugins 選項
                                      plugins: [autoprefixer(['IE 10'])]
                                  }
                              }
                          ]
                      }
                  ]
              }
          };
          
          /* package.json:受限于 json 的語法,可擴展性較弱,一般不推薦 */
          {
              "postcss": {
                  "plugins": {
                      "autoprefixer": "IE 10"
                  }
              }
          }
          

          6. 常見的 PostCss 插件

          以下羅列幾種常用的 PostCSS 插件,詳細用法參見各自的官網或相關文檔。

          Autoprefixer

          給 css 補齊各種瀏覽器私有的前綴,例如 -webkit、-moz、-ms 等,當然還會處理各種兼容性問題,比如 flex 語法,不能簡單添加 -webkit 就解決,還需要處理成 -webkit-box 這類老版本的標準。

          Autoprefixer 的主要參數就是 browserslist。

          postcss-preset-env

          postcss-preset-env 是跟 babel 的 preset-env 類似的功能,不用一一引入要用的插件,在打包構建的時候,會根據不同的配置輸出對應支持的 CSS 文件。

          PreCSS

          可以寫類似 Sass 和 cssnext 語法的 CSS。

          cssnano

          CSS 壓縮優化。

          四 代碼規范工具配置

          1. ESLint

          npm install eslint --save-dev
          

          安裝之后,可以通過使用 npx eslint 直接運行,在運行之前,我們需要創建個 ESLint 的配置文件,使用 eslint --init 命令創建 .eslintrc.json 文件。

          .eslintrc.json 內容示例,具體可查看 eslint 官網文檔:

          {
              "env": {
                  "browser": true,
                  "es6": true
              },
              "extends": "airbnb-base",
              "globals": {
                  "Atomics": "readonly",
                  "SharedArrayBuffer": "readonly"
              },
              "parserOptions": {
                  "ecmaVersion": 2018,
                  "sourceType": "module"
              },
              "rules": {
                  // 禁止 console,要用寫 eslint disbale
                  'no-console': 2,
                  // 禁止 debugger,防止上線
                  'no-debugger': 2,
                  // 禁止 alert,要用寫 eslint disable
                  'no-alert': 2,
                  // 不用的 var,要刪除,手動 tree shaking,要潔癖
                  'no-unused-vars': 2,
                  // 沒定義就用的就別用,全局的要用 寫 eslint global
                  'no-undef': 2
              }
          }
          

          ESLint 的報錯類型包括三種:off、warn和error,分別對應著:0、1、2,所以上面的配置的 rule 實際為error級別的規則,檢測到了則直接報錯誤(Error)。

          webpack 中的配置:

          npm install  eslint-loader --save-dev
          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.js$/,
                          loader: 'eslint-loader',
                          enforce: 'pre', // 調整了 loader 加載順序,保證先檢測代碼風格,之后再做 Babel 轉換等工作
                          include: [path.resolve(__dirname, 'src')], // 指定檢查的目錄
                          options: { // 這里的配置項參數將會被傳遞到 eslint 的 CLIEngine
                              formatter: require('eslint-friendly-formatter') // 指定錯誤報告的格式規范
                          }
                      }
                  ]
              }
          };
          
          

          2. StyleLint

          StyleLint 的配置文件是.stylelintrc.json,其中的寫法跟 ESLint 的配置類似

          npm install -D stylelint
          
          /* .stylelintrc.json */
          {
              "extends": ["stylelint-config-standard", "stylelint-config-recess-order"],
              "rules": {
                  "at-rule-no-unknown": [true, {"ignoreAtRules": ["mixin", "extend", "content"]}]
              }
          }

          webpack 中配置:

          const StyleLintPlugin=require('stylelint-webpack-plugin');
          
          module.exports={
              // ...
              plugins: [new StyleLintPlugin(options)]
              // ...
          };

          默認 StyleLint-webpack-plugin 會查找項目中的 StyleLint 配置文件,根據配置文件的配置來檢測 CSS 代碼。

          五 靜態資源管理

          前端的靜態資源一般指圖片、字體文件、富媒體等。

          1. 圖片引入方式

          圖片引入的一般方式有,Html 引入,Css 引入和 Javascript 的引入。在 webpack 中可以使用 loader 來處理加載圖片。

          file-loader 與 url-loader

          這是最常見的處理圖片的兩種 loader。它倆區別在于:

          • file-loader: 能夠根據配置項復制使用到的資源和構建之后的文件夾,并且能夠更改對應的鏈接
          • url-loader: 包含 file-loader 的全部功能,并且能歐根據配置將文件轉換成 Base64 的形式,以此減少 http 請求,實現一定程度上的優化。如果圖片較大,Base64 會很長,會導致打包后的 js/css 文件很大。

          webpack 的配置如下,使用 publicPath 可做靜態資源的 CDN 處理,可以使用 resolve.alias 做別名處理:

          // webpack.config.js
          const HTMLPlugin=require('html-webpack-plugin');
          
          module.exports={
              mode: 'development',
              entry: './src/index.js',
              // output: {
              //     publicPath: 'http://bd.bxstatic.com/img/'
              // }
              devtool: false,
              module: {
                  // resolve: {
                  //     alias: {
                  //         '@assets': path.resolve(__dirname, './src/assets')
                  //     }
                  // },
                  rules: [
                      {
                          test: /\.html$/,
                          use: ['html-loader']
                      },
                      {
                          test: /\.css$/,
                          use: ['style-loader', 'css-loader']
                      },
                      {
                          test: /\.(png|svg|jpg|gif)$/,
                          use: {
                              loader: 'url-loader',
                              options: {
                                  // url-loader 默認會做 Base64 處理,這里限制不超過 3k 大小的圖片才做 Base64 處理
                                  limit: 3*1024
                              }
                          }
                      }
                  ]
              },
              plugins: [
                  new HTMLPlugin({
                      template: './src/index.html'
                  })
              ]
          };
          

          在 Html 和 Css 中用別名的方式引入圖片時,要在別名前加~符號:

          <img src="~@assets/img/large.png" alt="背景圖" />
          .bg-img {
              background: url(~@assets/img/small.png) no-repeat;
          }

          svg-url-loader

          svg-url-loader 的工作原理類似于 url-loader,主要用來處理 SVG 文件。 svg-url-loader 擁有改善 IE 瀏覽器支持的選項,但是在其他瀏覽器中很糟糕。如果你需要兼容 IE 瀏覽器,設置 iesafe: true選項。

          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.svg$/,
                          loader: 'svg-url-loader',
                          options: {
                              // 小于 10kB(10240字節)的內聯文件
                              limit: 10 * 1024,
                              // 移除 url 中的引號
                              // (在大多數情況下它們都不是必要的)
                              noquotes: true
                          }
                      }
                  ]
              }
          };

          img-webpack-loader

          img-webpack-loader 用來對圖片進行壓縮優化,支持 JPG、PNG、GIF 和 SVG 格式的圖片,不過必須和 url-loader 以及 svg-url-loader 一起使用。

          module.exports={
              module: {
                  rules: [
                      {
                          test: /\.(jpe?g|png|gif|svg)$/,
                          loader: 'image-webpack-loader',
                          //提高優先級,保證在url-loader和svg-url-loader之前完成圖片優化
                          enforce: 'pre'
                      }
                  ]
              }
          };
          

          postcss-sprites

          將小圖標合成雪碧圖。需要結合 postcss-loader 使用。

          // postcss.config.js
          const postcssSprites=require('postcss-sprites');
          
          module.exports={
              plugins: [
                  postcssSprites({
                      // 在這里制定了從哪里加載的圖片被主動使用css sprite
                      // 可以約定好一個目錄名稱規范,防止全部圖片都被處理
                      spritePath: './src/assets/img/'
                  })
              ]
          };
          
          //webpack.config.js
          module.exports={
              module: {
                  rules: [
                      {
                      test: /\.css$/,
                      use: [
                          MiniCssExtractPlugin.loader,
                          'css-loader',
                          {
                              loader: 'postcss-loader'
                          }
                      ]
                  }
                  ]
              }
          };
          

          2. 字體、富媒體處理

          可以直接使用 url-loader 或者 file-loader 進行配置即可,不需要額外的操作。如果不需要 Base64,那么可以直接使用 file-loader,需要的話就是用 url-loader。

          {
              // 文件解析
              test: /\.(eot|woff|ttf|woff2|appcache|mp4|pdf)(\?|$)/,
              loader: 'file-loader',
              query: {
                  // 這么多文件,ext不同,所以需要使用[ext]
                  name: 'assets/[name].[hash:7].[ext]'
              }
          }
          

          3. 數據

          類似 CSV、TSV 和 XML 等數據,那么我們需要單獨給它們配置相應的 loader。內置支持 JSON 數據。

           {
              test: /\.(csv|tsv)$/,
              use: [
              'csv-loader'
              ]
          },
          {
              test: /\.xml$/,
              use: [
              'xml-loader'
              ]
          }
          

          六 HTML 打包配置

          webpack 處理 html 頁面,一般是使用 html-webpack-plugin 插件。

          // 安裝
          npm install html-webpack-plugin --save-dev

          簡單配置示例

          const HtmlWebPackPlugin=require('html-webpack-plugin');
          
          module.exports={
              mode: 'development',
              entry: {
                  main: './src/index.js'
              },
              plugins: [new HtmlWebPackPlugin()]
              // 指定打包后頁面的名稱(默認index.html)和 title
              // plugins: [new HtmlWebPackPlugin({title: 'hello', filename: 'foo.html'})]
          };
          

          打包后會生成 index.html,內容如下:

          <!DOCTYPE html>
          <html>
              <head>
                  <meta charset="utf-8" />
                  <title>Webpack App</title>
                  <meta name="viewport" content="width=device-width, initial-scale=1" />
              </head>
          
              <body>
                  <script src="main.js"></script>
              </body>
          </html>
          

          指定Template打包

          指定一個 template,使打包后的 html 頁面是依據這個 template 來打包的,這樣 html 的內容我們可以自定義,比如我們需要打包后的文件有<div id="app"></div>節點。

          指定 template:

          <!DOCTYPE html>
          <html lang="en">
              <head>
                  <meta charset="UTF-8" />
                  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
                  <title>Webpack</title>
              </head>
              <body>
                  <h1>hello world</h1>
                  <div id="app"></div>
              </body>
          </html>
          

          webpack.config.js 配置:

          const HtmlWebPackPlugin=require('html-webpack-plugin');
          
          module.exports={
              mode: 'development',
              entry: {
                  main: './src/index.js'
              },
              plugins: [
                  new HtmlWebPackPlugin({
                      template: './src/index.html' // 指定模板
                  })
              ]
          };
          

          打包后的 html 文件:

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1.0">
              <meta http-equiv="X-UA-Compatible" content="ie=edge">
              <title>Webpack</title>
          </head>
          <body>
              <h1>hello world</h1>
              <div id="app"></div>
          <script src="main.js"></script></body>
          </html>

          多頁配置

          單一入口:

          const HtmlWebPackPlugin=require('html-webpack-plugin');
          
          const indexPage=new HtmlWebPackPlugin({
              template: './src/index.html',
              filename: 'index.html'
          });
          const listPage=new HtmlWebPackPlugin({
              template: './src/list.html',
              filename: 'list.html'
          });
          
          module.exports={
              mode: 'development',
              entry: {
                  main: './src/index.js'
              },
              plugins: [indexPage, listPage]
          };
          

          多入口:

          const HtmlWebPackPlugin=require('html-webpack-plugin');
          
          module.exports={
              mode: 'development',
              entry: {
                  index: './src/index.js',
                  list: './src/list.js'
              },
              plugins: [
                  new HtmlWebPackPlugin({template: './src/index.html', filename: 'index.html', chunks: ['index']}),
                  new HtmlWebPackPlugin({template: './src/list.html', filename: 'list.html', chunks: ['list']})
              ]
          };
          

          最佳實踐:

          /**
           * 1. /scripts/utils/index.js 
           * 使用 npm 庫 globby 讀取src/pages/*.js, 生成入口 entry
           */
          const path=require('path');
          const globby=require('globby');
          
          const getEntry=(exports.getEntry=()=> {
              // 異步方式獲取所有的路徑
              const paths=globby.sync('./pages/*.js', {
                  cwd: path.join(__dirname, './src')
              });
              const rs={};
              paths.forEach(v=> {
                  // 計算 filename
                  const name=path.basename(v, '.js');
                  let p=path.join('./src', v);
                  if (!p.startsWith('.')) {
                      // 轉成相對地址
                      p='./' + p;
                  }
          
                  rs[name]=p;
              });
              return rs;
          });
          
          console.log(getEntry());
          
          /**
           * 2. /scripts/utils/index.js
           * 遍歷 entry,生成 html-webpack-plugins 數組
           */
          const HtmlWebPackPlugin=require('html-webpack-plugin');
          
          exports.getHtmlWebpackPlugins=()=> {
              const entries=getEntry();
              return Object.keys(entries).reduce((plugins, filename)=> {
                  plugins.push(
                      new HtmlWebPackPlugin({
                          template: entries[filename],
                          filename: `${filename}.html`,
                          chunks: [filename]
                      })
                  );
                  return plugins;
              }, []);
          };
          
          /**
           * 3. webpack.config.js
           * require 封裝好的html-webpack-plugins 數組
           */
          
          const {getEntry, getHtmlWebpackPlugins}=require('./scripts/utils');
          
          module.exports={
              mode: 'development',
              getEntry(),
              plugins: [
                  ...getHtmlWebpackPlugins()
              ]
          };
          
          

          七 Webpack Dev Server 本地開發服務

          webpack-dev-server 是一個可以用來啟動本地服務的插件。通過命令啟動對應的服務。

          // 安裝
          npm install webpack-dev-server
          // 啟動命令
          npx webpack-dev-server
          
          /* 命令常用參數 */
          // 修改端口號和 host
          webpack-dev-server --port 3000 --host 127.0.0.1
          // 啟動inline 模式的自動刷新
          webpack-dev-server --hot --inline
          // 手動指定 webpack config 文件
          webpack-dev-server --config webpack.xxx.js
          // 指定 webpack 的 mode
          webpack-dev-server --mode development
          // watch 功能,文件發生變化則觸發重新編譯
          webpack-dev-server --watch
          // dev-server默認會將工作目錄(當前目錄)作為基本目錄,可以手動修改它
          webpack-dev-server --content-base ./build
          

          執行 webpack-dev-server 命令之后,它會讀取 Webpack 的配置文件(默認是 webpack.config.js),然后將文件打包到內存中(所以看不到dist文件夾的生產,Webpack 會打包到硬盤上),這時候打開 server 的默認地址:localhost:8080 就可以看到文件目錄或者頁面(默認是顯示 index.html,沒有則顯示目錄)。

          一般在項目開發中,啟動本地服務的命令會配置在 package.json 的 scripts 屬性中:

          {
              "scripts": {
                  "dev": "webpack-dev-server --mode development --config webpack.config.dev.js --hot --inline --port 3000"
              }
          }

          更多的時候,是通過 devServer 屬性直接配置在 webpack.config.js 中:

          const path=require('path');
          module.exports={
              devServer: {
                  contentBase: path.join(__dirname, 'dist'),
                  port: 9000, // 端口
                  hot: true, // 熱部署,開啟熱部署需要引入 HotModuleReplacementPlugin 插件
                  inline: true,
                  // proxy解決本地開發跨域的問題,/api所有請求都轉發到了baidu.com
                  proxy: {
                      '/api': 'http://baidu.com'
                      // secure: false // 支持 https
                  }
                  // 加載所有內部中間件之前和之后可以插入自定義的中間件
                  before(app, server) {
                      app.get('/api/mock.json', (req, res)=> {
                          res.json({hello: 'world'});
                      });
                  },
                  after(){}
          
              },
              plugins: [
                  // 添加 hmr plugin
                  new webpack.HotModuleReplacementPlugin()
              ]
          };
          

          HMR 即模塊熱替換(Hot Module Replacement)的簡稱,它可以在應用運行的時候,不需要刷新頁面,就可以直接替換、增刪模塊。

          八 注意事項

          開發環境和生產環境的配置可能不同,需要分開、判斷處理。

          開發 vue 一般通過集成了 webpack 的 vue-cli 創建項目,但如果直接使用 webpack 需要引入 vue-loader。

          作者:越谷
          鏈接:https://juejin.cn/post/7380262523852455963
          來源:稀土掘金

          TOC

          1.認識webpack

          • webpack是一個現代的JavaScript應用的靜態模塊打包工具
          • 1.模塊化
          • 在ES6之前,我們要想進行模塊化開發,就必須借助于其他的工具,讓我們可以進行模塊化開發。
          • 并且在通過模塊化開發完成了項目后,還需要處理模塊間的各種依賴,并且將其進行整合打包。 而webpack其中一個核心就是讓我們可能進行模塊化開發,并且會幫助我們處理模塊間的依賴關系。
          • 而且不僅僅是JavaScript文件,我們的CSS、圖片、json文件等等在webpack中都可以被當做


          • 2.打包
          • 將webpack中的各種資源模塊進行打包合并成一個或多個包(Bundle)
          • 并且在打包的過程中,還可以對資源進行處理,比如壓縮圖片,將scss轉成css,將ES6語法轉成ES5語法,將TypeScript轉成JavaScript等等操作。


          • 3.和grunt/gulp的對比
          • 如果你的工程模塊依賴非常簡單,甚至是沒有用到模塊化的概念。
          • 只需要進行簡單的合并、壓縮,就使用grunt/gulp即可。
          • 但是如果整個項目使用了模塊化管理,而且相互依賴非常強,我們就可以使用更加強大的webpack

          在這里插入圖片描述



          2.webpack的安裝

          • 安裝node.js(https://nodejs.org/zh-cn/)
          • 查看node版本 node -v
          • 全局安裝webpack npm install webpack@3.6.0 -g,指定了版本為3.6.0
          • 局部安裝webpack cd 對應目錄;npm install webpack@3.6.0 --save-dev
          • 其中--save-dev是開發時依賴,項目打包后不需要繼續使用
          • 為什么全局安裝后,還需要局部安裝呢?
          • 在終端直接執行webpack命令,使用的全局安裝的webpack
          • 當在package.json中定義了scripts時,其中包含了webpack命令,那么使用的是局部webpack


          3.webpack的起步

          • 創建目錄結構

          在這里插入圖片描述


          • 文件和文件夾解析:
          • dist文件夾:用于存放之后打包的文件
          • src文件夾:用于存放我們寫的源文件
          • main.js:項目的入口文件。
          • mathUtils.js:定義了一些數學工具函數,可以在其他地方引用,并且使用。
          • info.js:定義了一些變量信息


          • index.html:瀏覽器打開展示的首頁html
          • package.json:通過npm init生成的,npm包管理的文件


          • mathUtils.js function add(num1,num2){ return num1 + num2; } function mul(num1,num2){ return num1*num2; } module.exports={ add, mul }
          • info.js javascript<br />export const name='why';<br />export const height=180;<br />
          • main.js const {add,mul}=require('./mathUtils.js'); console.log(add(20,30)); console.log(mul(20,30)); import {name,height} from './info.js'; console.log(name); console.log(height); 注:可以看到main.js引入了其它js文件
          • webpack打包 webpack ./src/main.js ./dist/bundle.js
          • 打包后會在dist文件下,生成一個bundle.js文件
          • bundle.js文件,是webpack處理了項目直接文件依賴后生成的一個js文件,我們只需要將這個js文件在index.html中引入即可
          • index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script src="dist/bundle.js"></script> </body> </html>

          4.webpack的配置

          • 目標:簡化上面的打包命令
          • 1.創建webpack.config.js文件 const path=require('path') module.exports={ entry : "./src/main.js", output: { path: path.resolve(__dirname,'dist'), //動態獲取絕對路徑,__dirname是node中全局變量 filename : "bundle.js" }, }
          • 2.npm init,生成package.json文件,這里面是針對當前項目的主要描述文件(里面會生成所有安裝的依賴)

          在這里插入圖片描述


          • 3.局部安裝webpack----cd 當前目錄;npm install webpack@3.6.0 --save-dev,生成node模塊

          在這里插入圖片描述


          • 4.配置package.json文件,簡化命令

          在這里插入圖片描述


          • 5.命令npm run build

          5.loader的使用

          • 在開發中我們不僅僅有基本的js代碼處理,我們也需要加載css、圖片,也包括一些高級的將ES6轉成ES5代碼,將TypeScript轉成ES5代碼,將scss、less轉成css,將.jsx、.vue文件轉成js文件等等
          • 對于webpack本身的能力來說,對于這些轉化是不支持的。需要webpack擴展對應的loader
          • loader使用過程:
          • 步驟一:通過npm安裝需要使用的loader
          • 步驟二:在webpack.config.js中的modules關鍵字下進行配置


          5.1 css的loader使用

          • 1.創建css文件

          在這里插入圖片描述

          css<br />body {<br /> background-color:red; <br />}<br />

          • 2.main.js引用 //1.使用commonjs的模塊化規范 const {add,mul}=require('./js/mathUtils.js'); console.log(add(20,30)); console.log(mul(20,30)); //2.使用ES6的模塊化規范 import {name,height} from './js/info.js'; console.log(name); console.log(height); //3.依賴css文件 require("./css/normal.css")
          • 3.run build打包(報錯)

          在這里插入圖片描述


          • 4.https://v4.webpack.docschina.org/loaders/,配置cssloader文檔
          • 5.npm install --save-dev css-loader@2.0.2
          • 6.npm install style-loader@0.23.1 --save-dev
          • 7.配置webpack.json.js文件

          在這里插入圖片描述


          • 8.index.html的使用 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> 你好 <h2> 你好 </h2> <script src="dist/bundle.js"></script> </body> </html>

          5.2 less的loader使用(同理)

          • 1.創建less文件

          在這里插入圖片描述

          @fontSize: 50px; @fontColor: orange; body{ font-size: @fontSize; color: @fontColor; }

          • 2.引入less文件(main.js) //1.使用commonjs的模塊化規范 const {add,mul}=require('./js/mathUtils.js'); console.log(add(20,30)); console.log(mul(20,30)); //2.使用ES6的模塊化規范 import {name,height} from './js/info.js'; console.log(name); console.log(height); //3.依賴css文件 require("./css/normal.css") //4.依賴less文件 require("./css/special.less")
          • 3.npm install less-loader@4.1.0 --save-devnpm install less@3.9.0 --save-dev
          • 4.配置webpack.json.js文件

          在這里插入圖片描述


          • 5.打包 run build

          5.3 圖片文件處理

          • 1.創建img文件

          在這里插入圖片描述


          • 2.修改css文件 body { /* background-color:red; */ background-image: url("../img/timg.jpg"); }
          • 3.直接打包會出錯,需要安裝url-loader包 npm install url-loader@1.1.2 --save-dev
          • 4.修改webpack.json.js文件

          在這里插入圖片描述


          • 5.這時候打包會成功,但是換了一張的圖片就會報錯

          在這里插入圖片描述


          • 6、安裝file-loader處理大文件npm install file-loader@3.0.1 --save-dev
          • 7、再次打包即可成功

          在這里插入圖片描述

          注:可以發現,對于大的圖片打包成功會輸出到dist文件夾下,此時引用的話會找不到,需要配置下路徑

          • 8.修改webpack.config.js

          在這里插入圖片描述


          • 9.另外對于生成的圖片名字太長,我們可以配置下生成規則--webpack.config.js,表示生成名字+8位哈希值+擴展名

          在這里插入圖片描述


          5.4 babel的使用(es6轉es5)

          • 1.npm install --save-dev babel-loader@7 babel-core babel-preset-es2015
          • 2.配置webpack.json.js文件

          在這里插入圖片描述


          • run build

          6.webpack中配置Vue

          6.1 引入vue.js

          • 1 . npm install vue@2.5.21 --save 因為我們后續是在實際項目中也會使用vue的,所以并不是開發時依賴
          • 2 . main.js引入 //1.使用commonjs的模塊化規范 const {add,mul}=require('./js/mathUtils.js'); console.log(add(20,30)); console.log(mul(20,30)); //2.使用ES6的模塊化規范 import {name,height} from './js/info.js'; console.log(name); console.log(height); //3.依賴css文件 require("./css/normal.css") //4.依賴less文件 require("./css/special.less") //5.使用Vue進行開發 import Vue from "vue" new Vue({ el:'#app', data:{ name : 'codewhy' } })
          • 3.run build(報錯)---這個錯誤說的是我們使用的是runtime-only版本的Vue,

          在這里插入圖片描述


          • 4.修改webpack.config.js配置,即可成功

          在這里插入圖片描述


          • 5.index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body > <div id="app"> 你好 </div> <h2> 你好 </h2> <script src="dist/bundle.js"></script> </body> </html>

          6.2 el和template的區別

          • 正常運行之后,我們來考慮另外一個問題:
          • 如果我們希望將data中的數據顯示在界面中,就必須是修改index.html
          • 如果我們后面自定義了組件,也必須修改index.html來使用組件
          • 但是html模板在之后的開發中,我并不希望手動的來頻繁修改,是否可以做到呢?


          • 定義template屬性:
          • 在前面的Vue實例中,我們定義了el屬性,用于和index.html中的#app進行綁定,讓Vue實例之后可以管理它其中的內容
          • 這里,我們可以將div元素中的{{message}}內容刪掉,只保留一個基本的id為div的元素
          • 但是如果我依然希望在其中顯示{{message}}的內容,應該怎么處理呢?
          • 我們可以再定義一個template屬性,代碼如下:

          在這里插入圖片描述



          • 那么,el和template模板的關系是什么呢?
          • 在我們之前的學習中,我們知道el用于指定Vue要管理的DOM,可以幫助解析其中的指令、事件監聽等等。
          • 而如果Vue實例中同時指定了template,那么template模板的內容會替換掉掛載的對應el的模板。


          • 這樣做有什么好處呢?
          • 這樣做之后我們就不需要在以后的開發中再次操作index.html,只需要在template中寫入對應的標簽即可


          6.3 分離template模板

          • 書寫template模塊非常麻煩怎么辦呢?
          • 沒有關系,稍后我們會將template模板中的內容進行抽離。
          • 會分成三部分書寫:template、script、style,結構變得非常清晰。

          在這里插入圖片描述



          • 1 .App.vue文件 <template> <div> <h2 class="title">{{message}}</h2> <button @click="btnClick">按鈕</button> <h2>{{name}}</h2> <Cpn/> </div> </template> <script> import Cpn from "./Cpn.vue" export default { name:"App", components: { Cpn }, data(){ return { name : 'codewhy', message:"123" } }, methods:{ btnClick(){ } } } </script> <style scoped> .title{ color:green; } </style>
          • 2 .子組件Cpn.vue文件 <template> <div> <h2 class="title">我是cpn組件的標題</h2> <p>我是cpn組件的內容</p> <h2>{{name}}</h2> </div> </template> <script> export default { name:"Cpn", data(){ return { name : 'Cpn的組件的name', } }, methods:{ btnClick(){ } } } </script> <style scoped> .title{ color:green; } </style>
          • 3 .main.js引入App.vue //1.使用commonjs的模塊化規范 const {add,mul}=require('./js/mathUtils.js'); console.log(add(20,30)); console.log(mul(20,30)); //2.使用ES6的模塊化規范 import {name,height} from './js/info.js'; console.log(name); console.log(height); //3.依賴css文件 require("./css/normal.css") //4.依賴less文件 require("./css/special.less") //5.使用Vue進行開發 import Vue from "vue" // import App from "./vue/app" import App from './vue/App.vue' const app=new Vue({ el:'#app', // 如果同時有el和template,會直接用template 替換掉el內容 template: <App/> , components:{ App } })
          • 4 .index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body > <div id="app"> 你好 </div> <h2> 你好 </h2> <script src="dist/bundle.js"></script> </body> </html>

          7.認識plugin

          7.1 添加版權聲明

          • 在webpack.config.js配置如下

          在這里插入圖片描述


          • 重新打包

          在這里插入圖片描述


          7.2 HtmlWebpackPlugin

          • 目的:將index.html打包到dist中
          • 1.安裝插件npm install html-webpack-plugin@3.2.0 --sava-dev
          • 2.在webpack.config.js導入

          在這里插入圖片描述


          • 3.因為index.html的js 打包后會自動引入,所以注釋了dist 以及下面的內容 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body > <div id="app"> 你好 </div> <!-- <script src="dist/bundle.js"></script> --> </body> </html>
          • 4.最后生成的如下

          在這里插入圖片描述


          7.3 壓縮js的插件

          • 1.npm install uglifyjs-webpack-plugin@1.1.1 --save-dev
          • 2.配置webpack.config.js

          在這里插入圖片描述


          • 3.npm run build
          • 對js丑化

          在這里插入圖片描述



          8.plugin的使用搭建本地服務器

          • webpack提供了一個可選的本地開發服務器,這個本地服務器基于node.js搭建,內部使用express框架,可以實現我們想要的讓瀏覽器自動刷新顯示我們修改后的結果。
          • 不過它是一個單獨的模塊,在webpack中使用之前需要先安裝它
          • npm install --save-dev webpack-dev-server@2.9.1


          • 修改webpack.config.js
          • devserver也是作為webpack中的一個選項,選項本身可以設置如下屬性:
          • contentBase:為哪一個文件夾提供本地服務,默認是根文件夾,我們這里要填寫./dist
          • port:端口號
          • inline:頁面實時刷新
          • historyApiFallback:在SPA頁面中,依賴HTML5的history模式

          在這里插入圖片描述


          • 修改package.json文件

          在這里插入圖片描述


          • 開始熱部署npm run dev

          在這里插入圖片描述

          這樣就會實現,當文件改變的時候,頁面會自動修改,因為此時這些修改保存到了內存中,類似于java的熱部署

          • 補充1:(自動打開鏈接)

          在這里插入圖片描述


          • 補充2:js壓縮在開發中,不應該使用

          在這里插入圖片描述


          9.webpack的配置分離

          • 目的:開發時,使用一個配置文件;發布時使用另一個配置文件
          • npm install webpack-merge@4.1.5 --save-dev 安裝merge包,用于合并下面的配置文件
          • 所以將webpack.config.js抽離成3個文件
          • 1 . base.config.js const path=require('path') const webpack=require('webpack') const HtmlWebpackPlugin=require('html-webpack-plugin') const uglifyjsWebpackPlugin=require('uglifyjs-Webpack-plugin') module.exports={ entry : "./src/main.js", output: { path: path.resolve(__dirname,'../dist'), //動態獲取絕對路徑,__dirname是node中全局變量 filename : "bundle.js", //publicPath: 'dist/' }, plugins:[ new webpack.BannerPlugin('最終版權swz所有!'), new HtmlWebpackPlugin({ template:'index.html' }), //new uglifyjsWebpackPlugin() ], module: { rules: [ { test: /\.css/,//style¨E45Eloader將模塊的導出作為樣式添加到DOM中//css¨E45Eloader解析CSS文件后,使用import加載,并且返回CSS代碼//使用多個loader時,是從右向左use:¨E91E′style¨E45Eloader′,′css¨E45Eloader′¨E93E¨E125E,¨E123Etest:/¨E92E.less/, // style-loader 將模塊的導出作為樣式添加到 DOM 中 // css-loader 解析 CSS 文件后,使用 import 加載,并且返回 CSS 代碼 //使用多個loader時,是從右向左 use: ['style-loader','css-loader'] }, { test: /\.less/,//style¨E45Eloader將模塊的導出作為樣式添加到DOM中//css¨E45Eloader解析CSS文件后,使用import加載,并且返回CSS代碼//使用多個loader時,是從右向左use:¨E91E′style¨E45Eloader′,′css¨E45Eloader′¨E93E¨E125E,¨E123Etest:/¨E92E.less/, use: [{ loader: 'style-loader' // creates style nodes from JS strings }, { loader: 'css-loader' // translates CSS into CommonJS }, { loader: 'less-loader' // compiles Less to CSS }] }, { test: /\.(png|jpg|jpeg|gif)/i,use:¨E91E¨E123Eloader:′url¨E45Eloader′,options:¨E123E//當加載的圖片,小于limit時,會將圖片編譯成base64字符串形式//反之,需要使用file¨E45Eloader沒模塊進行加載limit:13000,//¨E91E¨E93E表示變量name:′img/¨E91Ename¨E93E.¨E91Ehash:8¨E93E.¨E91Eext¨E93E′¨E125E¨E125E¨E93E¨E125E,¨E123Etest:/¨E92E.m?js/i, use: [ { loader: 'url-loader', options: { //當加載的圖片,小于limit時,會將圖片編譯成base64字符串形式 //反之,需要使用file-loader沒模塊進行加載 limit: 13000, //[]表示變量 name: 'img/[name].[hash:8].[ext]' } } ] }, { test: /\.m?js/i,use:¨E91E¨E123Eloader:′url¨E45Eloader′,options:¨E123E//當加載的圖片,小于limit時,會將圖片編譯成base64字符串形式//反之,需要使用file¨E45Eloader沒模塊進行加載limit:13000,//¨E91E¨E93E表示變量name:′img/¨E91Ename¨E93E.¨E91Ehash:8¨E93E.¨E91Eext¨E93E′¨E125E¨E125E¨E93E¨E125E,¨E123Etest:/¨E92E.m?j exclude: , : { : , : { : [] } } }, { : s/,//exclude 排除,include包含/(node_modules|bower_components)/useloader'babel-loader'optionspresets'es2015'test/\.vue/,use:¨E91E′vue¨E45Eloader′¨E93E¨E125E¨E93E¨E125E,resolve:¨E123Ealias:¨E123E′vue/, : [] } ] }, :{ : { use'vue-loader'resolvealias'vue/,use:¨E91E′vue¨E45Eloader′¨E93E¨E125E¨E93E¨E125E,resolve:¨E123Ealias:¨E123E′vu: } }} e'"vue/dist/vue.esm.js"
          • 2 . prod.config.js const uglifyjsWebpackPlugin=require('uglifyjs-Webpack-plugin') const webpackMerge=require('webpack-merge') const baseConfig=require('./base.config') module.exports=webpackMerge(baseConfig, {plugins:[ new uglifyjsWebpackPlugin() ] })
          • 3 . dev.config.js const webpackMerge=require('webpack-merge') const baseConfig=require('./base.config') module.exports=webpackMerge(baseConfig, { devServer:{ contentBase: "./dist", inline: true } })
          • 修改配置文件package.json

          在這里插入圖片描述

          注:以上安裝的模塊的版本要對應!!!

          學習視頻: https://www.bilibili.com/video/BV15741177Eh?p=90&spm_id_from=pageDriver

          關概念

          前端模塊管理器(package management)

          Web應用的目前的開發是各個模塊組合起來(如:加載各種js插件),為了使用各個模塊,需要使用大量的script標簽引進模塊,這樣就造成了Web頁面比較臃腫,同時在瀏覽器調用時也需要發送大量的HTTP請求.

          為了解決這一問題,那么就需要使用前端模塊管理器來管理JavaScript腳本的依賴關系,自動加載各個模塊,使得網頁結構清晰合理.

          常用的前端模塊管理器:Bower,Browserify,Component,Duo

          WebPack

          安裝使用

          使用說明

          Switch to the directory containing webpack.config.js and run:

          ebpack for building once for development

          ebpack -p for building once for production (minification)

          ebpack --watch for continuous incremental build in development (fast!)

          webpack -d to include source maps

          簡單使用示例

          1. 項目初始化和模塊安裝

            npm init -y

            npm install jquery --save

            npm install webpack --save-dev

          2. 在項目根目錄下創建webpack的配置文件webpack.config.js

            var webpack=require('webpack');

            var commonsPlugin=new webpack.optimize.CommonsChunkPlugin('common.js');

            module.exports={

            //插件項

            plugins: [commonsPlugin],

            //頁面入口文件配置

            entry: './src',

            //入口文件輸出配置

            output: {

            path: 'builds',

            filename: 'bundle.js'

            },

            };

          3. 相關代碼文件

            根目錄下創建src和builds

            app的入口文件(ES5語法):

            src/index.js

            var $=require('jquery');

            $('body').html('Hello');

            項目根目錄下創建index.html

            <!DOCTYPE html>

            <html>

            <head></head>

            <body>

            <h1>My title</h1>

            <a>Click me</a>

            <script src="builds/common.js"></script>

            <script src="builds/bundle.js"></script>

            </body>

            </html>

          4. 運行WebPack命令編譯bundle.js

            執行命令node_modules\.bin\webpack后瀏覽器查看效果

          將Bootstrap示例代碼使用WebPack打包

          安裝所需的加載器

          npm install css-loader node-sass resolve-url-loader sass-loader style-loader url-loader file-loader --save

          解決jQuery全局問題

          npm install jquery --save-dev

          WebPack配置文件

          var webpack=require('webpack');

          var commonsPlugin=new webpack.optimize.CommonsChunkPlugin('common.js');

          module.exports={

          //插件項

          plugins: [commonsPlugin],

          //頁面入口文件配置

          entry: './src/main.js',

          //入口文件輸出配置

          output: {

          path: 'builds',

          filename: 'bundle.js'

          },

          module: {

          //加載器配置

          loaders: [

          {

          // 得到jquery模塊的絕對路徑

          test: require.resolve('jquery'),

          // 將jquery綁定為window.jQuery

          loader: 'expose?jQuery'

          },

          // 匹配各種資源文件

          {

          test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,

          loader: 'url-loader?limit=50000&name=[path][name].[ext]'

          },

          {

          test: /\.js/,

          loader: 'babel',

          },

          {

          test: /\.css$/,

          loader: 'style!css'

          },

          {

          test: /\.html/,

          loader: 'html',

          }

          ]

          },

          plugins:[

          new webpack.ProvidePlugin({

          // jQuery設置為全局變量

          $:"jquery",

          jQuery:"jquery",

          "window.jQuery":"jquery"

          })

          ]

          };

          入口文件main.js

          // 加載css資源

          require('./css/bootstrap.min.css');

          require('./css/bootstrap-theme.min.css');

          require('./css/theme.css');

          // 加載其他js資源

          //require('jquery');

          require('./js/bootstrap.min.js');

          require('./js/docs.min.js');

          require('./js/ie10-viewport-bug-workaround.js');

          這里是使用打包bootstrap源碼的方式,也可以使用npm install bootstrap --save的方式加載bootstrap

          打包運行與原生bootstrap的比較網絡傳輸速度

          測試效果圖

          注意:

          1. 測試前為了防止瀏覽器緩存需要清除瀏覽器緩存

          2. 如果靜態資源文件有些會經常變化,可采用分文件打包的方式進行打包

          參考文章

          前端模塊管理器簡介

          webpack入門——webpack功能集合的demo

          基于webpack搭建前端工程解決方案探索

          webpack中引用jquery的簡單實現


          主站蜘蛛池模板: av无码精品一区二区三区四区 | 国产精品视频一区二区三区不卡| 中文字幕人妻AV一区二区| 精品视频一区二区观看| 国产午夜精品一区二区三区| 国产精品第一区揄拍| 亚洲综合av永久无码精品一区二区 | 午夜无码视频一区二区三区| 无码国产精品一区二区免费式芒果 | 亚洲精品色播一区二区| 国产精品主播一区二区| 亚洲国产成人久久一区二区三区| 亚洲国产av一区二区三区| 亚洲AV无码一区二区三区网址 | 久久无码精品一区二区三区| 久久精品视频一区二区三区| 无码中文字幕人妻在线一区二区三区 | 久久精品一区二区| 黄桃AV无码免费一区二区三区| 韩国一区二区三区视频| 日韩一区二区三区四区不卡| 色婷婷一区二区三区四区成人网 | 国产一区二区三区视频在线观看| 精品欧洲av无码一区二区| 精品一区二区三区东京热 | 国产短视频精品一区二区三区| 日韩美女视频一区| 久久无码人妻一区二区三区| 一本一道波多野结衣一区| 国产精品亚洲高清一区二区 | 国产在线一区二区| 在线视频亚洲一区| 韩国理伦片一区二区三区在线播放 | 精品视频无码一区二区三区| 久久亚洲AV午夜福利精品一区| 波多野结衣久久一区二区| 国产一区二区精品久久| 精品一区二区三区中文| 久久毛片一区二区| 国产一区二区福利| 制服中文字幕一区二区|