目錄
五、es6模塊化
把功能進行划分,將同一類型的代碼整合在一起,所以模塊的功能相對復雜,但都同屬於一個業務
為什么有模塊化
- js是按順序加載的,所以一般相互依的js是具有強制性的
- 多個js文件定義的引用會污染全局變量,多人協作開發可能會有沖突
- 可以用閉包
閉包解決多人協作開發
- 只需要寫好自己的模塊化的命名,就可以很好的避免沖突了,相當於把所有的容錯點都聚焦在一個點上,犯錯的機會就少了,
- 但是代碼的復用性還是很差
// ;是為了防止其他的導入js相互影響
;var xm01 = (function xiaoming01() {
return {
aa:"asdas",
flag: true
};
}())
//js文件2
;(function () {
if (xm01.flag) {
alert("xm01.flag:" + xm01.flag);
}
}());
組件化類似模塊化的更細粒度,組件充當了基本類庫一樣的東西目的是復用拓展性,模塊主要是以功能區分類別划分盡量隔離其他業務
模塊化練習
-
xiaoming01.js
// es6的導出,02中導入 export let exa = "222"; let exa1 = "333"; let exb = "333"; export {exb, exa1}; export function fun(){ console.log("asasddsds"); } //export default :import的時候可以自定義命名,一個js中只能有一個default let aaa="export default"; export default aaa;
-
xiaoming02.js
// 導入 ,這里需要寫上.js import {exa, exa1, exb} from "./xiaoming01.js"; // 01 console.log(exa1, exb); //導入default可以自定義命名 import asd from "./xiaoming01.js"; console.log('export:',asd); //導入全部的導出,並且重命名 import * as all from "./xiaoming01.js"; console.log(all); console.log(all.default)
-
01-es6.html
- script需要指定type=module
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./xiaoming01.js" type="module"></script> <script src="./xiaoming02.js" type="module"></script> </head> <body> 沒有使用導入導出的話: Uncaught ReferenceError: flag is not defined at xiaoming02.js:3 以前是可以執行的先在不知道怎么執行不了了 </body> </html>
六、webpack
webpack起步
*webpack* 是一個現代 JavaScript 應用程序的*靜態模塊打包器(module bundler)*。當 webpack 處理應用程序時,它會遞歸地構建一個*依賴關系圖(dependency graph)*,其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 *bundle*(捆,束),它做的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),並將其打包為合適的格式以供瀏覽器使用。
-
入口js
//commonjs規范 const {add} = require('./mathUtil.js'); console.log(add(1,3)); //es6規范 import {result} from "./es6.js"; console.log(result);
-
es6規范
const result = 45456;
export {result};
- common規范
function add(a, b) {
return a + b;
}
module.exports = {add};
webpack配置
- 導出的時候es6和commonjs不能在一個模塊中混用
- 配置webpack.config.js:要使用commonjs規范
//node的包里面的path模塊,用來拼接絕對路徑
const path = require('path');
//這里要用commonjs導出,不能用es6
module.exports = {
//打包轉換的調用入口和main方法類似
entry: './src/main.js',
ouput: {
//必須使用絕對路徑,path.resolve(__dirname,'dist')返回絕對路徑
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js'
}
};
- package.json配置:json不能有注釋
{
"name": "meetpackage",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//npm run build 會在這個配置文件中找webpack命令,這個使用的是本地的命令,
//不是全局的webpack,本地是針對於你的這個開發項目
"build":"webpack"
},
"author": "",
//開發的依賴
"devDependencies": {
"webpack": "^3.6.0"
},
//開源才需要這個,json中不能注釋
"license": "ISC"
}
- 本地安裝:開發時依賴 npm install webpack@3.6.0 --save-dev
- 終端terminal里敲的命令都是全局的
為什么使用--save-dev而不是--save?
-
-save 會把依賴包名稱添加到 package.json 文件 dependencies 下;
-
-save-dev 則添加到 package.json 文件 devDependencies 鍵下;
webpack-loader
- 官網可以找到對應的loader安裝
- 例:npm install style-loader[@version] --save -dev[表示開發環境用]
- npm install babel-loader@7 babel-core babel-preset-es2015 --save-dev es6轉es5
//node的包里面的path模塊,用來拼接絕對路徑
const path = require('path');
//這里要用commonjs導出,不能用es6
module.exports = {
entry: './src/main.js',
output: {
//必須使用絕對路徑
path: path.resolve(__dirname,'dist'),
filename: 'bundle.js',
//為所有的url相關的添加路徑
publicPath:'dist/'
},
module:{
rules: [
{
test: /\.css$/,
// style-loader將模塊的導出作為樣式添加到 DOM 中
// loader解析 CSS 文件后,使用 import 加載,並且返回 CSS 代碼
// 從右到左的順序加載
use: [ 'style-loader', 'css-loader' ]
},
// {
// test: /\.(png|jpg|gif)$/,
// use: [
// {
// loader: 'url-loader',
// options: {
// //限制圖片大小,大於limit會找file-loader
// limit: 9999
// }
// }
// ]
// },
// 在使用webpack進行打包時,對圖片路徑的處理方法常用的有兩種,一種是file-loader,
// 一種是url-loader,當我們使用其中一種是,請把另一種刪掉,不然會出現圖片無法正常顯示的問題
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
//name是文件名,hash取8位,ext是拓展名
name:'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
]
}
};
webpack-vue
-
npm install vue -save
-
不寫路徑默認從node_modules引入 import Vue from 'vue'
-
runtime-only:是運行的時候代碼不能包含任意一個template標簽
-
runtime-compiler:代碼中可以有template標簽
- 解決3.4碰到的問題
module:{ resolve:{ alias:{ // vue$正則,表示導入的時候會檢測vue指向的文件夾,如果這里不指定,會去找默認的runtime-only 'vue$':'vue/dist/vue.esm.js' } }
//使用vue
import Vue from 'vue';
const App = {
template: `
<h2>{{msg}}</h2>
`,
data() {
return {
msg: 'hello world'
};
}
};
new Vue({
el: '#app',
// template和el關系是,這里的template會替換el的標簽
template: `<App/>`,
components: {
App
}
});
將組件的代碼提出去
- 新建一個.vue文件
<template>
<h2>{{msg}}</h2>
<span class="title">{{tit}}</span>
</template>
<script>
export default {
name: "App",
data() {
return {
msg: 'hello world',
tit:'title'
};
}
}
</script>
<style scoped>
.title{
color: red;
}
</style>
- npm install vue-loader vue-template-compiler --save -dev
- 會出現版本過高的問題 安裝一個低版本的
- 編輯package.json中的版本號,會根據你的大版本找一個合適的,必須重新npm install
webpack-plugin
- 安裝打包靜態文件:npm install --save-dev html-webpack-plugin
- 壓縮js文件替換變量為更簡單的:npm install uglifyjs-webpack-plugin@1.1.1 --save -dev 指定的vueCli 2
webpack-dev-server
-
全局安裝:可以不用
npm install webpack-dev-server -g
-
開發環境:
npm install webpack-dev-server -save -dev
-
配置參數:
--content-base //設定webpack-dev-server的director根目錄。如果不進行設定的話,默認是在當前目錄下。 --quiet: //控制台中不輸出打包的信息,開發中一般設置為false,進行 打印,這樣查看錯誤比較方面 --no-info: // 不顯示任何信息 --colors: //對信息進行顏色輸出 --no-colors: //對信息不進行顏色輸出 --compress: //開啟gzip壓縮 --host <hostname/ip>: //設置ip --port <number>: //設置端口號,默認是:8080 --inline: //webpack-dev-server會在你的webpack.config.js的入口配置文件中再添加一個入口, --hot: //開發熱替換 --open: //啟動命令,自動打開瀏覽器 --history-api-fallback: //查看歷史url
-
兩種方式:
- 直接scripts中使用:"dev": "webpack-dev-server --contentBase src --port 80 --hot --colors"
- 配置文件:
plugins: [ new webpack.BannerPlugin('最終版權是小明'), //打包靜態資源,並且指定模板 new htmlWebpackPlugin({ template:`index.html` }), //壓縮js new UglifyJsWebpackPlugin(), //熱加載,不會全部加載,只加載改動的地方,配置了hot就需要配置,直接在命令中使用--hot就不需要配置這個插件 // new webpack.HotModuleReplacementPlugin() ], // devServer: { // contentBase: 'src', // port: 80, // hot:true // },
-
報錯可能是版本問題
webpack.config.js配置文件
//node的包里面的path模塊,用來拼接絕對路徑
const path = require('path');
const webpack = require('webpack');
const htmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJsWebpackPlugin = require('uglifyjs-webpack-plugin');
//這里要用commonjs導出,不能用es6
module.exports = {
entry: './src/main.js',
output: {
//必須使用絕對路徑
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
//為所有的url相關的添加路徑
// publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.css$/,
// style-loader將模塊的導出作為樣式添加到 DOM 中
// loader解析 CSS 文件后,使用 import 加載,並且返回 CSS 代碼
// 從右到左的順序加載
use: ['style-loader', 'css-loader']
},
// {
// test: /\.(png|jpg|gif)$/,
// use: [
// {
// loader: 'url-loader',
// options: {
// //限制圖片大小,大於limit會找file-loader
// limit: 9999
// }
// }
// ]
// },
// 在使用webpack進行打包時,對圖片路徑的處理方法常用的有兩種,一種是file-loader,
// 一種是url-loader,當我們使用其中一種是,請把另一種刪掉,不然會出現圖片無法正常顯示的問題
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
//name是文件名,hash取8位,ext是拓展名
name: 'img/[name].[hash:8].[ext]'
}
}
]
},
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test: /\.vue$/,
use: {
loader: 'vue-loader'
}
}
]
},
resolve: {
// 這寫拓展名可以省略
extensions: ['.css', '.js', '.vue'],
alias: {
// vue$正則,表示導入的時候會檢測vue指向的文件夾,如果這里不指定,會去找默認的runtime-only
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new webpack.BannerPlugin('最終版權是小明'),
//打包靜態資源,並且指定模板
new htmlWebpackPlugin({
template:`index.html`
}),
//壓縮js
new UglifyJsWebpackPlugin(),
//熱加載,不會全部加載,只加載改動的地方,配置了hot就需要配置,直接在命令中使用--hot就不需要配置這個插件
// new webpack.HotModuleReplacementPlugin()
],
// devServer: {
// contentBase: 'src',
// port: 80,
// hot:true
// },
};
抽取分離配置文件
-
創建三個配置文件:
- base.config.js : 存放公共的配置
//node的包里面的path模塊,用來拼接絕對路徑 const path = require('path'); const webpack = require('webpack'); const htmlWebpackPlugin = require('html-webpack-plugin'); //這里要用commonjs導出,不能用es6 module.exports = { entry: './src/main.js', output: { //必須使用絕對路徑 path: path.resolve(__dirname, '../dist'), filename: 'bundle.js', }, module: { rules: [ { test: /\.css$/, // style-loader將模塊的導出作為樣式添加到 DOM 中 // loader解析 CSS 文件后,使用 import 加載,並且返回 CSS 代碼 // 從右到左的順序加載 use: ['style-loader', 'css-loader'] }, { test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { //name是文件名,hash取8位,ext是拓展名 name: 'img/[name].[hash:8].[ext]' } } ] }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['es2015'] } } }, { test: /\.vue$/, use: { loader: 'vue-loader' } } ] }, resolve: { // 這寫拓展名可以省略 extensions: ['.css', '.js', '.vue'], alias: { // vue$正則,表示導入的時候會檢測vue指向的文件夾,如果這里不指定,會去找默認的runtime-only 'vue$': 'vue/dist/vue.esm.js' } }, plugins: [ new webpack.BannerPlugin('最終版權是小明'), //打包靜態資源,並且指定模板 new htmlWebpackPlugin({ template: `index.html` }) ], };
-
dev.config.js : 存放開發時配置
const WebpackMerge = require('webpack-merge'); const baseConfig = require('./base.config'); module.exports = WebpackMerge(baseConfig, { devServer: { contentBase: 'src', port: 80, inline: true } });
-
prod.config.js : 存放生產時配置
const UglifyJsWebpackPlugin = require('uglifyjs-webpack-plugin'); const WebpackMerge = require('webpack-merge'); const baseConfig = require('./base.config'); module.exports = WebpackMerge(baseConfig, { plugins: [ //壓縮js new UglifyJsWebpackPlugin() ] });
-
修改scripts
- 可刪除默認的webpack.config.js
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --config ./build/dev.config.js", "build": "webpack --config ./build/prod.config.js" },
打包
-
使用webpack,也可以不用配置文件自己在命令后指定參數,以下是使用配置文件
-
使用npm,會找到package.json找到對應的script里的命令執行,實際上還是調用了webpack命令