兩萬字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等等操作.
二、webpack安裝
準備工作
- 我們創建如下文件和文件夾:
- 文件和文件夾解析:
- 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
- 打包後會在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會從入口開始查找其他依賴的文件。
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/
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
-
npm安裝vue
npm install vue --save
-
依賴引入vue並使用
-
指定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參數表示直接打開瀏覽器