webpack配置

文章中以 $ 符號開頭的是在終端輸入的命令 
文章中以 vim 開頭爲編輯文件內容javascript

從零開始

$ mkdir dailypaper
新建一個項目文件夾dailypaper
$ npm init
    在該文件夾下npm init初始化項目文件夾會產生package.json文件
$ npm install -D webpack    
    本地局域安裝webpack依賴
$ npm install -D webpack-dev-server   
     開發環境安裝服務器熱更新依賴
$ mkdir app        
    建立app文件夾用來存放放原始代碼文件
$ mkdir public      
     建立public文件夾用來存放打包後的文件
$ touch webpack.config.js    
    建立web pack.config.js 配置文件

webpack.config.js配置文件四大重要組成部分:入口文件、出口文件、loader、插件plugins

vim web pack.config.js 初始化webpack.config.js的內容css

var config = {

};
module.exports = config;

這裏的module.exports = config;至關於export default config;。因爲目前尚未安裝支持ES6的編譯插件,所以不能直接用ES6的語法,不然會報錯。html

vim package.json 的scripts裏添加快速啓動熱更新服務的腳本vue

{
    //…
    "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "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和端口都是能夠配置的,如:java

vim package.jsonnode

"scripts": {
    "dev": "webpack-dev-server —-host 172.172.172.1 —-port 8888 —-open --config webpack.config.js",
    },

通常在局域網中,須要其餘同事訪問時能夠這樣設置,不然默認就能夠webpack

入口出口配置

Webpack配置 最重要的是兩項配置入口(Entry)和出口(Output),在dailypaper文件夾下新建一個空的app.js做爲入口的文件,再進行web

在dailypaper文件下npm

$ touch app.js
    新建app.js文件

vim web pack.config.js中json

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

};
module.exports = config;

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

在dailypaper文件下

$ touch index.html
    新建index.html文件
  • vim index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
</head>
<body>
    <div id="app">
        Hello World
    </div>
    <script src="./public/main.js"></script>
</body>
</html>

而後就能夠執行如下命令了:

$ npm run dev    
    就能打開網頁顯示Hello World了

vim app.js 打開dailypaper文件夾下的app.js,添加一行代碼

document.getElementById('app').innerHTML = 'Hello webpack.';

此時頁面已經自動變成了Hello webpack. 
此時看瀏覽器開發者工具的network視圖中(刷新頁面)的main.js有幾千行代碼,這是在開發環境下,大多都是webpack-dev-server的功能,只在開發時有效,在生產環境下編譯就不會這麼臃腫,執行如下命令打包

$ webpack —progress —hide-modules    打包 沒有壓縮

這時public 下的main.js就只有幾十行

loader配置

webpack配置除了入口和出口,須要進一步配置來實現更強大的功能 
每一個文件都是一個模塊,不一樣的模塊須要不一樣的加載器loaders來處理,加載器是webpack最重要的功能,經過安裝不一樣的加載器能夠對各類後綴名的文件進行處理,好比CSS樣式須要用到 style-loaderloader和 css-loader

$ install css-loader style-loader -D
安裝完成後再在webpack.config.js中配置Loader,增長對css文件的處理

vim web pack.config.js

var path = require('path');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test:/\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            }
        ]
    }

};

module.exports = config;

在 module 對象中的 rules 屬性中能夠指定一系列的 loaders ,每個 loader 必須包含 test 和 use 兩個選項, 
以上意思是,當遇到後綴名爲.css的文件時,先將它經過 css-loader 轉換,再經過 style-loader 轉換,而後繼續打包,use的值能夠是字符串或者數組,若是是數組,它的編譯順序是從後往前。

dailypaper文件夾下

$ touch style.css
    新建style.css,並在app.js中導入

vim style.css

#app {
    font-size:24px;
    color:#f50;
}

vim 在app.js中

import './style.css’;    //配置了loader以後,就能夠直接這麼將樣式文件經過import引入js 文件中
document.getElementById('app').innerHTML = 'Hello webpack.';

插件配置

CSS是經過JS動態建立 style 標籤來寫入的, 這意味着代碼已經編譯在了main.js中,但在實際業務中,樣式文件會不少,都放在JS裏太佔體積,還不能作緩存。這時候須要用到另外一個重要——插件(Plugin) 
這裏可使用一個 extract-text-webpack-plugin 的插件來將散落在各地的CSS提取出來,並生成一個main.css文件,最終在index.html裏經過 的形式加載。

$ npm install extract-text-webpack-plugin -D

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

vim web pack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test:/\.css$/,
                // use: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取後的CSS文件,此時必需要在index.html中引用纔會有樣式效果,打包成一個main.css
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

vim Index.html 必需要使用 link 標籤來引用纔會有樣式展現

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="/public/main.css">
</head>
<body>
    <div id="app">
        Hello World
    </div>
    <script src="/public/main.js"></script>
</body>
</html>

進階配置

引入 .vue 單文件與Vue-loader

.vue單文件組件須要使用 vue-loader 轉換處理 
一個 .vue 文件包括 template script style 三部分

$ touch app.vue
    app 文件夾下 新建 app.vue

vim app.vue

<template>
    <div> 你好,單文件組件</div>
</template>

<script>
    export default {

    }
</script>

<style scoped >
    div {
        color:red;
    }
</style>

scoped 表示當前的CSS只在當前組件內有效,若是不加,會應用到整個項目,lang=‘less’ 表示使用 less 預編譯處理

使用 .vue 文件須要先安裝 vue-loader vue-style-loader 等加載器並作配置 
另外要使用ES6語法,須要安裝 babel 和 babel-loader 等加載器。

$ npm install -S vue
$ npm install -D vue-loader
$ npm install -D vue-style-loader
$ npm install -D vue-template-compiler
$ npm install -D vue-hot-reload-api
$ npm install -D babel
$ npm install -D babel-loader
$ npm install -D babel-core
$ npm install -D babel-plugin-transform-runtime
$ npm install -D babel-preset-es2015
$ npm install -D babel-runtime

安裝完成後,添加配置

vim webpack.config.js 來支持對 .vue 以及 ES6 的解析;

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        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: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取後的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

vue-loader 在編譯 .vue 文件時,會對

// document.getElementById('app').innerHTML = 'Hello webpack.’;

import './style.css';
import App from './app/app.vue';
import Vue from 'vue';

new Vue({
    el: '#app',
    render: h => h(App)    //這裏不能直接寫爲components: { App },template:’<App></App>’,會報錯

})

而後就能夠

$ npm run dev 在瀏覽器中能夠看到app.vue組件的內容替換了index.html 中的 id =‘app' 的 div

生產環境

進一步配置webpack

安裝 url-loader file-loader 來支持圖片、字體等文件;

$ npm install url-loader file-loader -D

vim webpack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname,'./public'),
        publicPath: '/public/',
        filename: 'main.js'
    },
    module: {
        rules: [
            {
                test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
                loader: 'url-loader?limit=1024'
            },
            {
                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: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback:'style-loader'
                })
            }
        ]
    },
    plugins:[
        //重命名提取後的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;

當遇到 .gif .png .ttf 等格式文件時,url-loader 會把它們一塊兒編譯到 public 目錄下, 「?limit=1024」是指若是這個文件小於1kb,就以base64 的形式加載,不會生成一個文件。 
在app.vue 中加載一個圖片。

vim app.vue

<template>
    <div> 
        <h1>你好,單文件組件</h1>
        <p>
            nice to see you!
        </p>
        <img src="./img/snow.jpg" width="300">
    </div>
</template>

<script>
    export default {
        name:'app',
        data(){
            return {

            }
        }

    }
</script>

<style scoped lang='less'>
    div {
        color:red;
        p {
            color:blue;
        }
    }
</style>

打包上線

打包後的產物: 
單頁面富應用(SPA)最終只有一個html 文件,其他都是靜態資源,實際部署到生產環境時,通常會將html 掛在後端程序下,由後端路由渲染這個頁面,將全部的靜態資源(CSS JS、image、iconfont等)單獨部署到CDN,固然也能夠和後端程序部署在一塊兒,這樣就實現了先後端徹底分離。 
咱們在webpack 的output 選項裏已經指定了path 和publicPath ,打完包後,全部的資源都會在dailypaper/public 目錄下。

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

$ npm install webpack-merge -D
$ npm html-webpack-plugin -D

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

vim 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: '/public_CDN/',
        //將入口文件重命名爲帶有20位hash值的惟一文件
        filename: 'static/js/[name].[hash].js'    //filename定義的路徑就在打包配置的public文件夾下
    },
    plugins: [
        new ExtractTextPlugin({
            //提取CSS, 並重命名爲帶有20位hash值的惟一文件
            filename: 'static/css/[name].[hash].css',
            allChunks: true
        }),
        //定義當前的code 環境爲生產環境
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        //壓縮 JS
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            }
        }),
        //提取模板,並保存入口html文件
        new HtmlwebpackPlugin({
            filename: 'index_prod.html',//在public文件夾下,index_prod.html與static在同一目錄下,
            template: './index.ejs',
            inject: false
        })
    ]
})

其中/public_CDN/須要修改成部署存放static文件夾的CDN服務器地址。 
上面安裝的web pack-merge 模塊就是用於合併兩個webpack的配置文件,因此prod的配置是在web pack_config.js的基礎上擴展的,靜態資源大部分場景下都有緩存(304),更新上線後通常都但願用戶能及時地看到內容,因此給打包後的CSS和JS文件的名稱都加了20位的hash值,這樣文件名就惟一了,只要不對html 設置緩存,上線後就能加載最新的靜態資源。 
Html-webpack-plugin 是用來生成 .html 文件的, 它經過 template 選項來讀取指定的模板 index.ejs, 而後輸出到 filename 指定的目錄, 也就是 public/index_prod.html。

下面是模板 index.ejs 動態設置了靜態資源的路徑和文件名 該文件在dailypaper目錄下 
vim index.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="<%= htmlWebpackPlugin.files.css[0] %>">
</head>
<body>
    <div id="app">

    </div>
    <script type='text/javascript' src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
</body>
</html>

ejs 是一個JavaScript 模板庫,用來從JSON 數據中生成HTML 字符串, 經常使用語Node.js

vim webpack.config.js

var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var config = {
    entry: {
        app: './app'
    },
    output: {
        path: path.join(__dirname, './public/'),
        publicPath: '/public/‘,
        filename: 'main.js'
    },
    module: {
        rules: [{
                test: /\.(gif|jpg|png|woff|svg|eot|ttf)\??.*$/,
                loader: 'url-loader?limit=1024&name=images/[hash:8].[name].[ext]’   //打包多個圖片時
                //name 字段指定了在打包根目錄(output.path)下生成名爲 images 的文件夾,並在原圖片名前加上8位 hash 值
            },
            {
                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: [
                //     'style-loader',
                //     'css-loader'
                // ]
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style-loader'
                })
            }
        ]
    },
    plugins: [
        //重命名提取後的CSS文件
        new ExtractTextPlugin("main.css")
    ]

};

module.exports = config;
$ npm run build     //打包
此時打包後的 index_prod.html在public 文件夾下,打包後的代碼以下所示

打包以後的Index_prod.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>dailypaper</title>
    <link rel="stylesheet" type="text-css" href="/public_CDN/static/css/app.ba3073bb7bb28cda7d30.css">
</head>
<body>
    <div id="app">

    </div>
    <script type='text/javascript' src="/public_CDN/static/js/app.ba3073bb7bb28cda7d30.js"></script>
</body>
</html>

打包以後的目錄以下

打包目錄

相關文章
相關標籤/搜索