前端工程化基礎-vue

由淺入深支持更多功能javascript

 

1.安裝最新版本的node.js和NPM,並瞭解NPM基本用法。css

2.建立一個目錄demo。使用npm 初始化配置: npm init  ,執行後會有一系列選項,可按回車快速確認,在demo中生成一個package.json文件。html

3.局部安裝webpack  :  npm install webpack --save-devvue

--save-dev 會做爲開發依賴來安裝webpack。安裝成功後,在package.json中會多一項配置java

"devDependencies": {
  "webpack": "4.6.0"  
}

4.接着須要安裝webpack-dev-server,它能夠在開發環境中提供不少服務,好比啓動一個服務器,熱更新,接口代理等node

局部安裝: npm install webpack-dev-server --save-devwebpack

5.在demo下建立一個js文件:webpack.config.js初始化內容:es6

var config = {
    
};

module.exports = config;

6.在package.json的script裏增長一個快速啓動webpack-dev-server服務的腳本:web

{
  //...
    "scripts":{
          "test":*****,
          "dev":"webpack-dev-server --open --config webpack.config.js"        
      }    
    
}

當運行npm run dev就會執行webpack-dev-server --open --config webpack.config.js命令。其中--config是指向webpack-dev-server 讀取的配置文件路徑,這裏直接讀取咱們在上一步建立的webpack.config.js文件。--open會在執行命令是打開瀏覽器頁面,默認地址是127.0.0.1:8080,不過ip和端口均可以配置。npm

"dev":"webpack-dev-server --host 172.172,172.1 --port 8888 --open --config webpack.config.js"

通常用默認的本機地址就能夠。

7.在demo目錄下新建一個空的main.js做爲入口的文件,而後在webpack.config.js中進行入口的輸出和配置:

var path = require('path');
var config = {
    entry: {
        main: './main'
    },
    output: {
        path: path.join(__dirname, '/dist'),
        publicPath: './dist',
        filename: 'main.js'
    }
};

module.exports = config;

entry中的main就是咱們配置的單入口,webpack會從main.js文件開始工做。output中path選項用來存放打包後文件的輸出目錄,必填項。publicPath是資源文件引用目錄,若是在cdn上,這裏能夠填寫cdn地址。filename用於指定輸出文件的名稱。所以,這裏配置的output意爲打包後的文件會存放在demo/dist/main.js,只在html引入就能夠了。

<body>
    <div id="app">Hello world</div>
<script src="/dist/main.js"></script>
</body>

8.運行 npm run dev就能看到hello world字樣。

 

9.逐步完善配置文件

在webpack的世界中,每一個文件都是一個模塊,好比.css、.js、.html、.jpg、.less等。對於不一樣的模塊須要用不一樣的加載器來處理,而加載器就是webpack最重要的功能。

安裝style-loader和css-loader來處理css樣式。

經過npm 來安裝:

npm install css-loader --save-dev

npm install style-loader --save-dev

安裝完成後再webpack.config.js文件裏面配置Loader,增長對.css文件的處理。

var config = {
    //.....
    module:{
        rules:[
            {
                test:/\.css$/,
                use:[
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }
};

module對象 的rules屬性中能夠指定一系列的loader,每個loader都必須包含test和use兩個選項。這段的意思是說,當webpack編譯過程當中遇到require()或import語句導入一個後綴名爲.css的文件時,先將它經過css-loader轉換,再經過style-loader轉換,而後繼續打包。use選項的值能夠是數組或字符串,若是是數組,它的編譯順序就是從後往前。

在demo下新建一個style.css文件,並在main.js中導入:

/**style.css**/

#app{
  font-size:24px;

  color:#f50;
}

//main.js

import './style.css'

從新執行npm run dev能夠看到頁面文字變成了紅色,字號變大。

下面是執行後的html源碼:

能夠看到,css是經過javascript動態建立style標籤來寫入的,這意味着樣式代碼都已經編譯在了mian.js文件裏,可是在實際業務中可能並不但願這樣作,由於項目大了樣式會不少,都放在js裏太佔體積。這時 就要用到webbpack的插件。

webpack的插件功能很強大並且能夠定製。這裏咱們使用一個extract-text-webpack-plugin的插件來把散落在各地的css提取出來,並生成一個main.css的文件,並最終在index.html裏經過link的形式加載它。

 10.經過npm 安裝extract-text-webpack-plugin插件:

npm install extract-text-webpack-plugin --save-dev

而後在配置文件中導入插件,並改寫loader配置:

 

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    //.....
    module:{
        rules:[
            {
                test:/\.css$/,
                use:ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style.loader'
                })
            }
        ]
    },
    plugin: [
        //重命名提取後的css文件
        new ExtractTextPlugin("main.css")
    ]
};

module.exports = config;

這個時候運行可能會出現「DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead」相似的報錯,這個是webpack版本問題

使用 sudo npm install extract-text-webpack-plugin@next  安裝4.0就可解決這個問題。

 

11.單文件組件和vue-loader

在使用webpack構建Vue項目時,可使用一種新的構建模式:.vue單文件組件。在webpack中使用vue-loader就能夠對.vue格式的文件進行處理。

一個.vue文件通常包含3部分,<template>、<script>、<style>

style標籤使用scoped屬性,表示當前的css只在這個組件有效,若是不加,那麼樣式會應用到整個項目。style還能夠結合css預編譯一塊兒使用。好比less處理就能夠寫成<style lang="less">。使用.vue文件須要安裝 vue-loader,vue-style-loader等加載器並作配置。由於要使用es6語法,還需安裝babel和babel-loader等加載器。使用npm 逐個安裝如下依賴:

npm install --save vue

npm install --save-dev vue-loader

npm install --save-dev vue-style-loader

npm install --save-dev vue-template-compiler

npm install --save-dev vue-hot-reload-api

npm install --save-dev babel

npm install --save-dev babel-loader

npm install --save-dev babel-core

npm install --save-dev babel-plugin-transform-runtime

npm install --save-dev babel-preset-es2015

npm install --save-dev babel-runtime

12.安裝完成後,在webpack.config.js配置以支持.vue文件和es6的解析。

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        main:'./main'
    },
    output: {
        path: path.join(__dirname, '/dist'),
        publicPath: '/dist',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders :{
                        css: ExtractTextPlugin.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader'
                        })
                    }
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style-loader'
                })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin("main.css")
    ]
};

module.exports = config;

vue-loader在編譯.vue文件時,會對<template>、<script>、<style>分別處理,因此在vue-loader選項裏多了一項options來進一步對不一樣語言進行配置。好比在對css進行處理時,會先經過css-loader解析,而後把處理結果再交給vue-style-loader處理。當技術棧多樣化時,能夠給<template>、<script>、<style>都指定不一樣的語言,好比<template lang="jade">和<style lang="less">,而後配置loader就能夠了。

13.在demo目錄下新建一個名爲.babelrc的文件,並寫入babel的配置,webpack會依賴此配置文件來使用babel編譯es6代碼:

{
  "presets": ["es2015"],
  "plugins": ["transform-runtime"],
  "comments": false
}

配置好這些後就可使用.vue文件了,每一個.vue文件就表明一個組件,組件之間能夠相互依賴。

14.在demo目錄下新建一個app.vue的文件並寫入如下內容:

<template>
    <div>Hello {{name}}</div>
</template>

<script>
    export default {
        data() {
            return {
                name: "vue.js"
            }
        }
    }
</script>

<style scoped>
    div{
        color: #f60;
        font-size: 24px;
    }
</style>

.vue的組件時沒有名稱的,在父組件使用時能夠對它自定義。寫好了組件,就能夠在入口main.js中是用它了。打開main.js,把內容替換下面代碼:

import Vue from 'vue';
//導入app.vue組件
import App from './app.vue';

//建立Vue實例
new Vue({
    el: "#app",
    render: h => h(App)
});

 

render:h => h(App)是es6的寫法,等同於

render:function(h){

  return h(App)

}

執行npm run dev,這樣第一個vue工程項目就跑起來了。

bug:這個地方vue-loader升級到15版本以上不兼容。須要退回14版本才兼容。

這裏之因此多了一串data-v-xxx內容,是由於使用了<style scope>功能,若是去掉scope就沒有了。

15.在demo 目錄下新建兩個文件,title.vue和button.vue 

 title.vue

<template>
    <h1>
        <a :href="'#' + title">{{title}}</a>
    </h1>
</template>

<script>
    export default {
        props:{
            title:{
                type:String
            }
        }
    }
</script>

<style scoped>
    h1 a{
        color: #3399ff;
        font-size: 24px;
    }
</style>

button.vue

 

<template>
    <button @click="handleClick" :style="styles">
        <slot></slot>
    </button>
</template>

<script>
    export default {
        props: {
            color: {
                type: String,
                default: '#00cc66'
            }
        },
        computed:{
            styles () {
                return {
                    background: this.color
                }
            }
        },
        methods:{
            handleClick:function(e){
                this.$emit('click',e);
            }
        }
    }
</script>

<style scoped>
    button{
        border: 0;
        outline: none;
        color: #fff;
        padding: 4px 8px;
    }
    button:active{
        position: relative;
        top: 1px;
        left: 1px;
    }

</style>

而後改寫根實例app.vue組件,把title.vue和button.vue導入:

<template>
    <div>
        <v-title title="Vue組件化"></v-title>
        <v-button @click="handleClick">點擊按鈕</v-button>
    </div>
</template>

<script>
    //導入組件
    import vTitle from './title.vue';
    import vButton from './button.vue';

    export default {
        components: {
            vTitle,
            vButton
        },
        methods:{
            handleClick:function(e){
                console.log(e)
            }
        }

    }
</script>

<style scoped>
    div {
        color: #f60;
        font-size: 24px;
    }
</style>

其中components: {

  vTitle,

  vButton

}

寫法是es6寫法,等同於:

components: {

  vTitle : vTitle,

  vButton : vButton

}  

導入的組件都是局部註冊的,並且能夠自定義名稱,其餘用法和組件用法一致。

 

用於生產環境

咱們先對webpack進一步配置,來支持更多的經常使用功能。

安裝 url-loader 和 file-loader來支持圖片,字體等文件:

npm install --save-dev  url-loader

npm install --save-dev file-loader

//webpack.config.js

            {
                test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/, loader: 'url-loader?limit=1024' }

當遇到.gif、.png、.ttf等格式文件時,url-loader會把它們一塊兒編譯到dist目錄下,"limit=1024"表示若是這個文件小於1kb,就以base64的形式加載,不會生產一個文件。

找一張圖片,保存爲demo/images/image.png,並在app.vue中加載它:

<template>
    <div>
        <v-title title="Vue組件化"></v-title>
        <v-button @click="handleClick">點擊按鈕</v-button>
        <p>
            <img src="./images/image.png" style="width: 300px">
        </p>
    </div>
</template>

webpack打包後的產物:

單頁面富應用(SPA)技術,意味着最終只有一個html文件,其他都是靜態資源。實際部署到生產環境,通常都會將html掛載後端程序下,由後端路由渲染這個頁面,將全部的靜態資源(css、js、image、iconfont等)單獨部署到CDN,固然也能夠和後端程序部署在一塊兒,這樣就實現了先後端徹底分離。

在webpack的output選項裏指定了path和publicPath,打完包後,全部的資源都會保存在demo/dist目錄下。

打包會用到下面兩個依賴,使用NPM安裝:

npm install --save-dev webpack-merge

npm install --save-dev html-webpack-plugin

爲了方便開發和生產環境的切換,咱們在demo目錄下再新建一個用於生產環境的配置文件  webpack.prod.config.js

編譯打包,直接執行webpack命令就能夠。在package.json中,再加入一個build的快捷腳本用來打包:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --open --config webpack.config.js", "build": "webpack --progress --hide-modules --config webpack.prod.config.js" },

webpack.prod.config.js的代碼以下:

var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require('extract-text-webpack-plugin'); var merge = require('webpack-merge'); var webpackBaseConfig = require('./webpack.config.js'); //清空基本配置的插件列表 webpackBaseConfig.plugins = []; module.exports = merge(webpackBaseConfig, { output: { publicPath: '/dist/', //將入口文件重命名爲帶有20位hash值的惟一文件 filename: '[name].[hash].js' }, plugins: [ new ExtractTextPlugin({ //提取css,並重命名爲帶有20位hash值得惟一文件 filename: '[name].[hash].css', allChunks: true }), //定義當前node環境爲生產環境 new webpack.DefinePlugin({ 'process.env': { NODE_ENV: '"production"' } }), //壓縮js new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }), //提取模板,並保存入口html文件 new HtmlwebpackPlugin({ filename: '../index_prod.html', template: './index.ejs', inject: false }) ] });

上面安裝的webpack-merge模塊就是用於合併兩個webpack的配置文件,因此prod的配置是在webpack.config.js基礎上擴展的。靜態資源在大部分場景下都有緩存,更新上線後通常都但願用戶能及時地看到內容,因此給打包後的css和js文件都加了20位的hash值,這樣文件名就惟一了,只要不對html文件設置緩存,上線後當即就能夠加載最新的靜態資源。

html-webpack-plugin是用來生成html文件的,它經過template選項累讀取指定的模板index.ejs,而後輸出到filename指定的目錄,也就是說demo/index_prod.html,模板index.ejs動態設置了靜態資源的路徑和文件名。

最後在終端運行npm run build,等一會就會打完包,成功後會在demo目錄下生成一個dist目錄,裏面就是打完包全部的靜態資源。

bug:webpack升級4以上,打包會報錯:

Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimization.minimize instead.

這是由於新版本把方法移除了。解決辦法1:在script裏面配置

"build": "webpack --mode production"

就會自動打包。

解決辦法2:webpack內置的JS壓縮插件不能使用了,能夠安裝uglifyjs-webpack-plugin插件,使用同其餘非內置插件。

相關文章
相關標籤/搜索