webpack,配置,上手,例子

1.webpack是什麼?
2.爲何要用webpack?
3.怎麼用webpack?css

webpack是什麼?
html

答:webpack是前端模塊化應用和開發的打包工具,解決前端模塊依賴的工具。打包全部的腳本,圖片,css。前端

爲何要用webpack?
答:使用webpack能夠讓前端開發變得工程化和模塊化,方便前端開發,提升開發速率。
webpack的主要優勢是:模塊化。
缺點是配置繁瑣。vue

怎麼使用webpack?
答:參考官網文檔:https://webpack.js.org/concepts/
或者中文文檔:https://www.webpackjs.com/concepts/
看完後還不知道怎麼用?請看個人使用例子。node


本例中使用webpack的目的:
1.前端開發獨立於後端使用webpack-dev-server,將頁面可在本地查看,webpack-dev-server中的proxy,代理後端藉口
2.用webpack的loader解析.vue後綴的文件
3.配置webpack的熱更新,使得修改前端代碼,頁面自動更新
4.利用webpack-merge區分開發環境的配置和生產環境的配置
5.自動解析生產頁面jquery

webpack依賴webpack.config文件,生產環境和開發環境對應不用的位置文件,共同的配置文件放在一塊兒
webpack

src 目錄
web

package.json文件中的配置npm

"scripts": {
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot --config ./webpack_config/webpack.config.development.js",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules --config ./webpack_config/webpack.config.production.js"
  },

webpack.config.common.js中的配置json

var path = require('path')
var webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin');

var glob = require('glob')
var files = glob.sync(path.resolve(__dirname, '../src/*/index.js'));
var newEntries = {};
const config = {
    entry: {
        vendor: [
            './public/bower_components/jquery/dist/jquery.js',
            './public/bower_components/bootstrap/dist/css/bootstrap.css',
            './public/bower_components/bootstrap/dist/js/bootstrap.js'
        ]
    },
    output: {
        path: path.resolve(__dirname, '../public/vue_dist/'),
        publicPath: '/vue_dist/',
        filename: '[name].js'
    },
    module: {
        rules: [{
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ],
            },
            {
                test: /\.scss$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader'
                ],
            },
            {
                test: /\.sass$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'sass-loader?indentedSyntax'
                ],
            },
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        // Since sass-loader (weirdly) has SCSS as its default parse mode, we map
                        // the "scss" and "sass" values for the lang attribute to the right configs here.
                        // other preprocessors should work out of the box, no loader config like this necessary.
                        'scss': [
                            'vue-style-loader',
                            'css-loader',
                            'sass-loader'
                        ],
                        'sass': [
                            'vue-style-loader',
                            'css-loader',
                            'sass-loader?indentedSyntax'
                        ]
                    }
                    // other vue-loader options go here
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
                use: [{
                    loader: 'url-loader',
                    options: {
                        limit: 10000
                    }
                }]
            },
            {
                test: path.resolve(__dirname, '../public/bower_components/jquery/dist/jquery.js'),
                use: [{
                    loader: 'expose-loader',
                    options: 'jQuery'
                }, {
                    loader: 'expose-loader',
                    options: '$'
                }]
            }
        ]
    },
    plugins: [
        new ManifestPlugin()
    ],
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        },
        extensions: ['*', '.js', '.vue', '.json']
    },
    performance: {
        hints: false
    }
}
console.log(files + '------------files-------------------------');

files.forEach(function(f) {
    var name = /.*\/(.*?\/index)\.js/.exec(f)[1]; //register/main這樣的文件名
    console.log(name + '------------name-------------------------');
    newEntries[name] = f;
});
console.log(newEntries + '------------newEntries-------------------------');

config.entry = Object.assign({}, config.entry, newEntries);



module.exports = config;

webpack.config.development.js 配置文件

const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
var glob = require('glob')
var files = glob.sync(path.resolve(__dirname, '../src/*/index.js'));
var plugins = [];
files.forEach(function(f) {
    var name = /.*\/(.*?\/index)\.js/.exec(f)[1]; //register/main這樣的文件名
    var plug = new HtmlWebpackPlugin({
        filename: path.resolve(__dirname, '../public/vue_dist/' + name + '.html'),
        chunks: ['vendor', name],
        template: path.resolve(__dirname, '../src/index.html'),
        inject: true
    });
    plugins.push(plug);
});
plugins.push(
    new webpack.optimize.CommonsChunkPlugin({
        names: ['vendor']
    }));
module.exports = merge(common, {
    plugins: plugins,
    devtool: '#eval-source-map',
    devServer: {
        historyApiFallback: true,
        noInfo: true,
        overlay: true,
        port: 8080,
        host: 'localhost',
        publicPath:'/vue_dist',
        proxy: [{
            context: ["/upload", "/phone",'/register','/users'],
            target: "http://127.0.0.1:3000",
        }],
        openPage: 'vue_dist/upload/index.html'
    },
    output: {
        path: path.resolve(__dirname, '../public/vue_dist/'),
        publicPath: '/vue_dist',
        filename: '[name].js'
    },
});

webpack.config.production.js 配置文件

const merge = require('webpack-merge');
const common = require('./webpack.config.common.js');
const path = require('path');
var webpack = require('webpack')
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
var fillter = ['upload']
var glob = require('glob')
var files = glob.sync(path.resolve(__dirname, '../src/*/index.js'));
var plugins = [];
files.forEach(function(f) {
    var name = /.*\/(.*?\/index)\.js/.exec(f)[1]; //register/main這樣的文件名
    var c = false;
    for (let f = 0; f < fillter.length; f++) {
        const element = fillter[f];
        if (name.indexOf(element) > -1) {
            c = true;
            break;
        }
    }
    if (!c) {
        var plug = new HtmlWebpackPlugin({
            filename: path.resolve(__dirname, '../public/vue_dist/' + name + '.html'),
            chunks: [name],
            template: path.resolve(__dirname, '../src/index.html'),
            inject: true
        });
        plugins.push(plug);
    }
});
plugins.push(
    new CleanWebpackPlugin(['vue_dist'], {
        // Absolute path to your webpack root folder (paths appended to this)
        // Default: root of your package
        root: path.resolve(__dirname, '../public/'),

        // Write logs to console.
        verbose: true,

        // Use boolean "true" to test/emulate delete. (will not remove files).
        // Default: false - remove files
        dry: false,

        // If true, remove files on recompile. 
        // Default: false
        watch: false,

        // Instead of removing whole path recursively,
        // remove all path's content with exclusion of provided immediate children.
        // Good for not removing shared files from build directories.
        exclude: ['files', 'to', 'ignore'],

        // allow the plugin to clean folders outside of the webpack root.
        // Default: false - don't allow clean folder outside of the webpack root
        allowExternal: false,

        // perform clean just before files are emitted to the output dir
        // Default: false
        beforeEmit: false
    })
)
module.exports = merge(common, {
    devtool: '#eval-source-map',
    plugins: plugins
});

if (process.env.NODE_ENV === 'production') {
    module.exports.devtool = '#source-map'
        // http://vue-loader.vuejs.org/en/workflow/production.html
    module.exports.plugins = (module.exports.plugins || []).concat([
        new webpack.DefinePlugin({
            'process.env': {
                NODE_ENV: '"production"'
            }
        }),
        new webpack.optimize.UglifyJsPlugin({
            sourceMap: true,
            compress: {
                warnings: false
            }
        }),
        new webpack.LoaderOptionsPlugin({
            minimize: true
        })
    ])
}

用到的插件:

CleanWebpackPlugin 刪除目錄專用

HtmlWebpackPlugin Plugin that simplifies creation of HTML files to serve your bundles

webpack-merge 合併webpack.config 文件

glob 找到匹配的文件

ManifestPlugin Webpack plugin for generating asset manifests. 生成打包列表like this

{
"register/index.js": "/vue_dist/register/index.js",
"register/index.js.map": "/vue_dist/register/index.js.map",
"upload/index.js": "/vue_dist/upload/index.js",
"upload/index.js.map": "/vue_dist/upload/index.js.map",
"vendor.js": "/vue_dist/vendor.js",
"vendor.js.map": "/vue_dist/vendor.js.map",
"element-icons.ttf": "/vue_dist/6f0a76321d30f3c8120915e57f7bd77e.ttf",
"glyphicons-halflings-regular.woff2": "/vue_dist/448c34a56d699c29117adc64c43affeb.woff2",
"glyphicons-halflings-regular.woff": "/vue_dist/fa2772327f55d8198301fdb8bcfc8158.woff",
"glyphicons-halflings-regular.ttf": "/vue_dist/e18bbf611f2a2e43afc071aa2f4e1512.ttf",
"glyphicons-halflings-regular.svg": "/vue_dist/89889688147bd7575d6327160d64e760.svg",
"glyphicons-halflings-regular.eot": "/vue_dist/f4769f9bdb7466be65088239c12046d1.eot"
}

expose-loader 解決全局變量的問題 like jQuery 和 $ 對應


webpack 配置總結
webpack配置目的,自動打包,熱加載,快速開發,將須要的部分配置好自動打包

打包策略

首先,項目打包策略遵循如下幾點原則:

選擇合適的打包粒度,生成的單文件大小不要超過500KB
充分利用瀏覽器的併發請求,同時保證併發數不超過6
儘量讓瀏覽器命中304,頻繁改動的業務代碼不要與公共代碼打包
避免加載太多用不到的代碼,層級較深的頁面進行異步加載
基於以上原則,我選擇的打包策略以下:

第三方庫如vue、jquery、bootstrap打包爲一個文件
公共組件如彈窗、菜單等打包爲一個文件
工具類、項目通用基類打包爲一個文件
各個功能模塊打包出本身的入口文件
各功能模塊做用一個SPA,子頁面進行異步加載

webpack配置
entry 入口文件,多入口。apps/question/index這樣的,則會生成對應的目錄結構
output 打包後的出口文件
plugin 插件
rules 文件處理
devserver 開發服務器,可代理接口,方便與後臺開發
.....

0.約定開發目錄結構
1.多入口,多出口,按須要的文件夾生成打包後的文件 glob
2.生產環境和開發環境分開配置,webpack-merg


若有錯漏,請多多指教!

相關文章
相關標籤/搜索