兩萬字Vue.js基礎學習筆記(二)

Vue.js學習筆記(二)

4、模組化開發

ES6模組化的導入和導出

  • 我們使用export指令導出了模組對外提供的介面,下面我們就可以通過import命令來載入對應的這個模組了
  • 首先,我們需要在HTML程式碼中引入兩個js文件,並且類型需要設置為module
  • import指令用於導入模組中的內容.比如main.is的程式碼

導出方法:

var name = '小明';
var age = 18;
var flag = true;

function sum(num1, num2) {
  return num1 + num2
}

if (flag) {
  console.log(sum(20, 30));
}

// 1.導出方式一:
export{
  flag,sum
}

// 2.導出方式二:
export var num1 = 100;
export var height = 1.88;

// 3.導出函數/類
export function mul(num1,num2){
  return num1+num2
}
export class Person{
  run(){
    console.log('再跑');
  }
}

// 5.export default
// 某些情況下, 一個模組中包含某個的功能,我們並不希望給這個功能命名,而且讓導入者可以自己來命名,只能有一個

// const address = "北京市";
// export default address;

export default function(argument){
  console.log(argument);
}

導入方法:

// 1.導入的{}中定義的變數
import {flag,sum} from "./aaa.js";
if(flag){
  console.log("小明666");
  console.log(sum(20,30));
}

// 2.直接導入export定義的變數
import{num1,height} from "./aaa.js";
console.log(num1);
console.log(height);

// 3.導入 export的function/class
import{mul,Person} from "./aaa.js";
console.log(mul(1000,100))
const p = new Person();
p.run();

// 4.導入export default中的內容
import addr from "./aaa.js";
addr('你好');

// 5.同一全部導入
import * as aaa from "./aaa.js";
console.log(aaa.flag)

5、Webpack

一、什麼是webpack

前端模組化:

  • 在前面學習中,我已經用了大量的篇幅解釋了為什麼前端需要模組化。
  • 而且我也提到了目前使用前端模組化的一些方案: AMD、CMD、CommonJS、 ES6。
  • 在ES6之前,我們要想進行模組化開發,就必須藉助於其他的工具,讓我們可以進行模組化開發。
  • 並且在通過模組化開發完成了項目後,還需要處理模組間的各種依賴,並且將其進行整合打包。
  • 而webpack其中一個核心就是讓我們可能進行模組化開發 ,並且會幫助我們處理模組間的依賴關係。而且不僅僅是JavaScript文件,我們的CSS、圖片、json文件等等在webpack中都可以被當做模組來使用(在後續我們會看到)。
  • 這就是webpack中模組化的概念。

打包如何理解呢?

  • 理解了webpack可以幫助我們進行模組化,並且處理模組間的各種複雜關係後,打包的概念就非常好理解了。
  • 就是將webpack中的各種資源模組進行打包合併成一個或多個包(Bundle)。
  • 並且在打包的過程中,還可以對資源進行處理比如壓縮圖片,將scss轉成css ,將ES6語法轉成ES5語法,將TypeScript轉成JavaScript等等操作.

image-20210712124430916

二、webpack安裝

image-20210712131815476

準備工作

  • 我們創建如下文件和文件夾:
  • 文件和文件夾解析:
    • dist文件夾:用於存放之後打包的文件
    • src文件夾:用於存放我們寫的源文件
      • main.js :項目的入口文件。具體內容查看下面詳情。
      • mathUtils.js :定義了一 -些數學工具函數 ,可以在其他地方引用,並且使用。具體內容查看下面的詳情。
    • index.html :瀏覽器打開展示的首頁html
    • package.json :通過npm init生成的, npm包管理的文件
  • mathUtils.js文件中的程式碼:
  • main.js文件中的程式碼:

JS文件的打包

  • 現在的js文件中使用了模組化的方式進行開發,他們可以直接使用嗎?不可以。
    • 因為如果直接在index.htmI引入這兩個js文件,瀏覽器並不識別其中模組化程式碼。
    • 外,在真實項目中當有許多這樣的js文件時,我們一個個引用非常麻煩,並且後期非常不方便對它們進行管理。
  • 我們應該怎麼做呢?使用webpack工具,對多個js文件進行打包。
    • 我們知道, webpack就是一個模組化的打包工墾 ,所以它支援我們程式碼中寫模組化,可以對模組化的程式碼進行處理。( 如何處理的,待會兒在原理中, 我會講解)
    • 另外,如果在處理完所有模組之間的關係後,將多個js打包到一個js文件中 ,引入時就變得非常方便了。
  • OK ,如何打包呢?使用webpack的指令即可
webpack ./src/main.js ./dist/bundle.js

image-20210712135530268

  • 打包後會在dist文件下,生成一個bundle.js文件
    • 文件內容有些複雜,這裡暫時先不看,後續再進行分析。
    • bundle.js文件,是webpack處理了項目直接文件依賴後生成的一個js文件,我們只需要將這個js文件在index.htmlI中引入即可

webpack.config.js和package.json的配置

webpack.config.js可以配置webpack的出入口

//引用node的基本包
const path = require('path');

// 指定webpack的出入口
module.exports = {
  entry: './src/main.js',
  output: {
    // 動態獲取路徑 絕對路徑
    path: path.resolve(__dirname,'dist'),
    filename: 'bundle.js'
  },
} 

package.json配置node腳本和依賴

{
  "name": "meetwebpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"  //npm run build 運行本地webpack而不是全局webpack
  },
  "author": "",
  "license": "ISC",
  "dependencies": {},
  "devDependencies": {
    "webpack": "^3.6.0"	//所依賴的webpack版本
  }
}

局部安裝webpack

npm install [email protected] --save-dev

三、Loader

  • loader是webpack中一個非常核心的概念。

  • webpack用來做什麼呢?

    • 在我們之前的實例中,我們主要是用webpack來處理我們寫的js程式碼,並且webpack會自動處理js之間相關的依賴。
    • 但是,在開發中我們不僅僅有基本的js程式碼處理,我們也需要載入css、圖片,也包括一些高級的將ES6轉成ES5程式碼,將TypeScript轉成ES5程式碼,將scss、less轉成css ,將jsx、.vue文件轉成js文件等等。
    • 對於webpack本身的能力來說,對於這些轉化是不支援的。
    • 那怎麼辦呢?給webpack擴展對應的loader就可以啦。
  • loader使用過程:

    • 步驟一 : 通過npm安裝需要使用的loader

    • 步驟二 : 在webpack.config.js中的modules關鍵字下進行配置

  • 大部分loader我們都可以在webpack的官網中找到,並且學習對應的用法。

CSS和LESS文件處理

  • 項目開發過程中,我們必然需要添加很多的樣式,而樣式我們往往寫到一個單獨的文件中。

    • 在src目錄中,創建一個css文件 ,其中創建一個normal.css文件。

    • 我們也可以重新組織文件的目錄結構,將零散的js文件放在一個js文件夾中。

  • normal.css中的程式碼非常簡單,就是將body設置為red

  • 但是,這個時候normal.css中的樣式會生效嗎?

    • 當然不會,因為我們壓根就沒有引用它。
    • webpack也不可能找到它,因為我們只有一個入口, webpack會從入口開始查找其他依賴的文件。

image-20210712153335881

mian.js

// 1. 使用commonjs的模組化規範
const {add, mul} = require('./js/mathUtils.js')
  
console.log(add(20,30));
console.log(mul(20,30));

// 2.使用ES6的模組化規範
import { name,age,height} from './js/info.js';
console.log(name);
console.log(age);
console.log(height);

// 3.依賴css文件
require('./css/normal.css')

// 4.依賴less文件
require('./css/special.less')
document.writeln('<h2>你好</h2><h2>')

在webpack裡面找到CSS的loader

安裝css-loader css-loader只負責將css文件進行載入

npm install --save-dev css-loader

安裝style-loader style-loader 把CSS樣式插入到DOM中

npm install --save-dev style-loader

使用多個loader時,是從右向左

webpack.config.js的配置

const path = require('path');

// 指定webpack的出入口
module.exports = {
  entry: './src/main.js',
  output: {
    // 動態獲取路徑 絕對路徑
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
        test: /\.css$/i,
        // css-loader只負責將css文件進行載入
        // style-loader 把CSS樣式插入到DOM中
        // 使用多個loader時,是從右向左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.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
        }]
      }
    ],
  },
}

圖片文件處理

安裝url-loader

npm install --save-dev url-loader

如果大於limit就要安裝file-loader

npm install --save-dev file-loader

配置webpack.config.js

{
        test: /\.(png|jpg|gif|jpeg)$/,
        use: [{
          loader: 'url-loader',
          options: {
            // 當載入圖片時,小於limit時,會將圖片編譯成base64字元串形式。
            // 當載入圖片時,大於limit時,需要使用file-loader模組進行載入。
            limit: 13000,
            name:'img/[name].[hash:8].[ext]'  //使圖片全部儲存在dist的img文件夾里且命名為 原來名字+8位hash值(防止重複)+.原來後綴
          },
        }]
      }

再次打包後dist文件夾會出現一個圖片文件

  • 我們發現webpack自動幫助我們生成- 個非常長的名字
    • 這是一個32位hash值,目的是防止名字重複
    • 但是,真實開發中,我們可能對打包的圖片名字有一定的要求
    • 比如,將所有的圖片放在一個文件夾中,跟上圖片原來的名稱,同時也要防止重複
  • 所以,我們可以在options中添加上如下選項:
    • img:文件要打包到的文件夾
    • name :獲取圖片原來的名字,放在該位置
    • hash:8 :為了防止圖片名稱衝突,依然使用hash ,但是我們只保留8位
    • ext :使用圖片原來的擴展名、
  • 但是,我們發現圖片並沒有顯示出來,這是因為圖片使用的路徑不正確
    • 默認情況下, webpack會將生成的路徑直接返回給使用者
    • 但是,我們整個程式是打包在dist文件夾下的,所以這裡我們需要在路徑下再添加一個dist/

image-20210712183557041

ES6語法處理

如果你仔細閱讀webpack打包的jis文件,發現寫的ES6語法並沒有轉成ES5 ,那麼就意味著可能一 些對ES6還不支援的瀏覽器沒有辦法很好的運行我們的程式碼。
在前面我們說過,如果希望將ES6的語法轉成ES5 ,那麼就需要使用babel。

  • 而在webpack中,我們直接使用babel對應的loader就可以了。

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

  • 	{
            test: /\.m?js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['es2015']
              }
            }
          },
    

Webpack配置Vue

  1. npm安裝vue

    npm install vue --save
    
  2. 依賴引入vue並使用

  3. 指定vue的版本

  • runtime-only 版本->程式碼中,不可以有任何的template
  • runtime-compiler 版本 >程式碼中,可以有template,因為有compiler可以用於編譯template

在webpack.config.js中配置

resolve: {
    alias: {
      'Vue$': 'vue/dist/vue.esm.js'
    }
  }

el和template區別

定義template屬性:

  • 在前面的Vue實例中,我們定義了el屬性,用於和index.htmI中的#app進行綁定,讓Vue實例之後可以管理它其中的內容

  • 這裡,我們可以將div元素中的{message}}內容刪掉,只保留一個基本的id為div的元素

  • 但是如果我依然希望在其中顯示{{message}}的內容,應該怎麼處理呢?

  • 我們可以再定義一個template屬性 ,程式碼如下:

  • new Vue({
      el: '#app',
      template: `
      <div>
        <h1>{{message}}</h1>
      </div>
      `,
      data: {
        message: 'Hello Webpack'
      }
    })
    

.vue文件的處理

從html中寫vue程式碼->main.js中寫vue程式碼->vue.js中寫vue程式碼

main.js中寫vue程式碼

// 5.使用vue進行開發
import Vue from 'Vue'

new Vue({
  el: '#app',
  template: `
  <div>
    <h1>{{message}}</h1>
  </div>
  `,
  data: {
    message: 'Hello Webpack'
  }
})

進行抽離獨立出來App.js

export default {
  template: `
  <div>
    <h1>{{message}}</h1>
  </div>
  `,
  data() {
    return {
      message: 'Hello Webpack11'
    }
  }
}

進一步抽離 Vue.js中寫vue程式碼

Vue.js

<template>
  <div>
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: "Hello Webpack11",
    };
  },

  components: {},

  computed: {},

  methods: {},
};
</script>
<style scoped="">
h1 {
  color: aqua;
}
</style>

Main.js

import Vue from 'Vue'
import App from './vue/App.vue'

new Vue({
  el: '#app',
  template: '<app>',
  components: {
    App
  }
})

打包vue文件

npm安裝vue-loader

npm install [email protected] vue-template-compiler --save-dev

webpack.config.js配置文件

{
        test: /\.vue$/,
        use: ['vue-loader']
      }

plugin插件

  • plugin是什麼?
    • plugin是插件的意思,通常是用於對某個現有的架構進行擴展。
    • webpack中的插件,就是對webpack現有功能的各種擴展,比如打包優化,文件壓縮等等。
  • loader和plugin區別
    • loader主要用於轉換某些類型的模組,它是一個轉換器。
    • plugin是插件,它是對webpack本身的擴展,是-個擴展器。
  • plugin的使用過程:
    • 步驟一: 通過npm安裝需要使用的plugins(某些webpack已經內置的插件不需要安裝)
    • 步驟二:在webpack.config.js中的plugins中配置插件。
  • 下面,我們就來看看可以通過哪些插件對現有的webpack打包過程進行擴容,讓我們的webpack變得更加好用。
const webpack = require('webpack')

plugins: [
    new webpack.BannerPlugin('最終版權歸洛依塵所有')
  ],

打包html的plugin

  • 目前,我們的index.html文件是存放在項目的根目錄下的。

    • 我們知道,在真實發布項目時 ,發布的是dist文件夾中的內容,但是dist文件夾中如果沒有index.html文件,那麼打包的js等文件也就沒有意義了。
    • 所以,我們需要將index.html|文件打包到dist文件夾中,這個時候就可以使用HtmlWebpackPlugin插件
  • HtmlWebpackPlugin插件可以為我們做這些事情:

    • 自動生成一個index.html文件(可以指定模板來生成)
    • 將打包的js文件,自動通過script標籤插入到body中
  • 安裝HtmlWebpackPlugin插件

    npm install [email protected] --save--dev
    
  • 使用插件,修改webpack.config.js文件中plugins部分的內容如下:

    • 這裡的template表示根據什麼模板來生成index.html
    • 另外,我們需要刪除之前在output中添加的publicPath屬性
    • 否則插入的script標籤中的src可能會有問題
    plugins: [
        new webpack.BannerPlugin('最終版權歸洛依塵所有'),
        new HtmlWebpackPlugin({
          template:'index.html'
          // 根據index.html模板生成
        })
      ],
    

js壓縮的Plugin

  • 在項目發布之前,我們必然需要對js等文件進行壓縮處理

    • 這裡,我們就對打包的js文件進行壓縮
    • 我們使用一個第三方的插件uglifyjs-webpack-plugin ,並且版本號指定1.1.1 ,和CL2保持-致
    npm install [email protected] --save-dev
    
  • 修改webpack.config.js文件,使用插件:

    plugins: [
        new webpack.BannerPlugin('最終版權歸洛依塵所有'),
        new HtmlWebpackPlugin({
          template:'index.html'
          // 根據index.html模板生成
        }),
        new UglifyjsWebpackPlugin()
      ],
    

搭建本地伺服器

  • webpack提供了一個可選的本地開發伺服器,這個本地伺服器基於node.js搭建,內部使用express框架,可以實現我們想要的讓瀏覽器自動刷新顯示我們修改後的結果。

  • 不過它是一-個單獨的模組,在webpack中使用之前需要先安裝它

    npm install --save-dev [email protected]
    
  • devserver也是作為webpack中的一個選項,選項本身可以設置如下屬性:

    • contentBase :為哪一個文件夾提供本地服務 ,默認是根文件夾,我們這裡要填寫./dist
    • port :埠號
    • inline :頁面實時刷新
    • historyApiFallback :在SPA頁面中,依賴HTML5的history模式
  • webpack.config.js文件配置修改如下:

    devServer:{
        contentBase:'./dist',
        inline:true,
      }
    
  • 我們可以再配置另外一個scripts :

    "dependencies": {
        "html-webpack-plugin": "^3.2.0",
        "uglifyjs-webpack-plugin": "^1.1.1",
        "vue": "^2.6.14"
      },
    

    –open參數表示直接打開瀏覽器