從零開始開發一個簡易的類vue-cli構建工具

 

代碼地址:https://github.com/cheer4chai/webpack-learningjavascript

仿照vue-cli開發這個工具的目的是瞭解webpack的基本設置,以及vue-cli的工做原理css

Series1.簡單的打包構建功能

webpack的配置很簡單: html

設置好入口文件:entry,輸出文件:outputvue

// webpack.config.js

module.exports = { entry: { bundle1: './main1.js', bundle2: './main2.js' }, output: { filename: '[name].js' }, module: { loaders: [{ test: /\.css$/, loader: 'style-loader!css-loader' }] } }

 

最終文件目錄: java

 

 

咱們發現webpack把main1.js和main2.js分別打包爲了bundle1和bundle2,main.css也打包到了bundle文件中,這樣咱們就初步打包成功了。node

 

Series2.使用loader將less/css文件打包

若是在webpack中須要將less/css等一些非js文件打包至目標文件時,咱們就須要用到webpack的特性之一:loaderjquery

其實只要在webpack的配置文件中加入module字段就能夠了,代碼以下webpack

let path = require('path')
let webpack = require('webpack');


module.exports = {
    entry: './src/entry.js',
    devtool: 'inline-source-map',
    output: {
        path: path.join(__dirname, '/dist'),
        filename: 'bundle.js',
        publicPath: '/dist/'
    },
    devServer: {
        contentBase: path.join(__dirname, "./"),
        hot: true,
    },
    module: {
        loaders: [{
                test: /\.css$/,
                loader: "style-loader!css-loader"
            },
            {
                test: /\.less$/,
                loader: "style-loader!css-loader!less-loader"
            }
        ]
    }
}

  另外值得一提的是loader是從右到左的鏈式操做,如上的css文件,是先通過css-loader處理,再通過style-loader處理,才能轉化爲所須要的打包格式git

 

Series3.使用webpack-dev-server在線瀏覽效果

當使用vue-cli的時候咱們會想,當運行npm run dev的時候他是怎麼生成一個本地的文件的呢,其實就是用了webpack-dev-server這一個插件,在本地用nodejs生成了一個服務器,代理了在內存中自動生成的靜態頁面。話很少說,安裝了這個插件以後(yarn add webpack-dev-server),只要在項目目錄下執行webpack-dev-server命令,訪問本地localhost:8080就能夠看到這個頁面了。github

可是這個時候當咱們修改了一個文件以後還須要從新用webpack編譯,再刷新頁面再能看到更改內容,那麼有什麼能夠解決這個問題嗎?沒錯,這個時候咱們就須要熱重載插件:HotModuleReplacementPlugin。其實也很簡單,只要在webpack的plugins內加入這個組件,另外在devServer中配置hot爲true(或者運行的時候執行--hot命令),就能夠實現熱重載了。

還須要一提的是HtmlWebpackPlugin插件,這個插件能夠自動生成一個HTML文件,vue-cli最終的html文件就是該文件生成的,所以咱們還須要這個插件去自動生成一個html文件引用output的js文件,並打開

讓咱們來看一下如何配置這幾個東西:

let path = require('path')
let webpack = require('webpack');
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: './src/entry.js',
    devtool: 'inline-source-map',
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    devServer: {
        hot: true,
        compress: true,
        publicPath: '/'
    },
    module: {
        loaders: [{
                test: /\.css$/,
                loader: "style-loader!css-loader"
            },
            {
                test: /\.less$/,
                loader: "style-loader!css-loader!less-loader"
            }
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(), // 熱加載
        new HtmlWebpackPlugin(),
    ]
}

  文件目錄以下:

在根目錄下運行webpack-dev-server,咱們就能夠在本地看到已經打包後的頁面了

 

Series4.使用webpack-merge分別設置webpack的dev及prod模式

由於在平常開發中,咱們每每會須要開發和生產兩種環境,而這兩個環境的webpack配置有相同的地方,又有不一樣的地方,這個時候咱們須要用的webpack-merge來將wepack的配置分紅兩個模式,相似於vue-cli那樣,分爲三個文件:base/dev/build,分別保存共用設置、開發用設置和生產設置。

文件以下:

//webpack.base.config
let path = require('path')

module.exports = {
    entry: {
        index: './src/main.js'
    },
    devtool: 'inline-source-map',
    output: {
        path: path.join(__dirname, 'dist'),
        filename: 'bundle.js',
        publicPath: '/'
    },
    resolve: {
        extensions: ['.js', '.vue', '.json'],
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }
    },
    module: {
        loaders: [{
                test: /\.vue$/,
                loader: 'vue-loader'
            }, {
                test: /\.css$/,
                loader: "style-loader!css-loader"
            },
            {
                test: /\.less$/,
                loader: "style-loader!css-loader!less-loader"
            }
        ]
    }
}

  

//webpack.dev.config
let path = require('path')
let webpack = require('webpack');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(baseWebpackConfig, {

    devServer: {
        hot: true,
        compress: true,
        publicPath: '/'
    },

    plugins: [
        new webpack.HotModuleReplacementPlugin(), // 熱加載
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true
        })
    ]
})

  

在生產模式中,爲了能夠生成更小的文件,已經實現js的按需引用,咱們配置webpack的CommonsChunkPlugin以及UglifyJsPlugin,其中chunk能夠將頁面中引用的第三方庫單獨打包,而uglify顧名思義,則是壓縮代碼須要的插件,詳細的配置以下:

 

//webpack.build.config
let path = require('path')
let webpack = require('webpack');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(baseWebpackConfig, {
    entry: {
        index: './src/main.js',
        vendor: ['jquery', 'vue']
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: path.join('static', 'js/[name].[chunkhash].js'),
        chunkFilename: path.join('static', 'js/[id].[chunkhash].js')
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: false,
            parallel: true
        }),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                    // more options:
                    // https://github.com/kangax/html-minifier#options-quick-reference
            },
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'ventor',
            minChunks: Infinity
        })
    ]
})

  目錄結構以下圖:

 


Series4.配置vue文件編譯

當咱們須要向vue-cli同樣,將vue都編譯成最終的js文件的時候,咱們須要一個新的loader:vue-loader,另外爲了讓webpack能夠引入template,咱們還須要在webpack中配置resolve字段

改動的代碼以下:

//webpack.dev.config
let path = require('path')
let webpack = require('webpack');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(baseWebpackConfig, {

    devServer: {
        hot: true,
        compress: true,
        publicPath: '/'
    },

    plugins: [
        new webpack.HotModuleReplacementPlugin(), // 熱加載
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true
        })
    ]
})

  

//webpack.build.config
let path = require('path')
let webpack = require('webpack');
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.config')

const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = merge(baseWebpackConfig, {
    entry: {
        index: './src/main.js',
        vendor: ['jquery', 'vue']
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: path.join('static', 'js/[name].[chunkhash].js'),
        chunkFilename: path.join('static', 'js/[id].[chunkhash].js')
    },
    plugins: [
        new webpack.optimize.UglifyJsPlugin({
            compress: {
                warnings: false
            },
            sourceMap: false,
            parallel: true
        }),
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'index.html',
            inject: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true
                    // more options:
                    // https://github.com/kangax/html-minifier#options-quick-reference
            },
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'ventor',
            minChunks: Infinity
        })
    ]
})

  

項目目錄以下圖:

 

 如圖,咱們已經實現了一個簡單的類vue-cli構建工具。詳細的代碼能夠去個人github看:https://github.com/cheer4chai/webpack-learning,若是能幫助到你,煩請點個star~

相關文章
相關標籤/搜索