代碼地址:https://github.com/cheer4chai/webpack-learning
仿照vue-cli開發這個工具的目的是了解webpack的基本設置,以及vue-cli的工作原理
Series1.簡單的打包構建功能
webpack的配置很簡單:
設置好入口文件:entry,輸出文件:output
// 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' }] } }
最終文件目錄:

我們發現webpack把main1.js和main2.js分別打包為了bundle1和bundle2,main.css也打包到了bundle文件中,這樣我們就初步打包成功了。
Series2.使用loader將less/css文件打包
如果在webpack中需要將less/css等一些非js文件打包至目標文件時,我們就需要用到webpack的特性之一:loader
其實只要在webpack的配置文件中加入module字段就可以了,代碼如下
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處理,才能轉化為所需要的打包格式
Series3.使用webpack-dev-server在線瀏覽效果
當使用vue-cli的時候我們會想,當運行npm run dev的時候他是怎么生成一個本地的文件的呢,其實就是用了webpack-dev-server這一個插件,在本地用nodejs生成了一個服務器,代理了在內存中自動生成的靜態頁面。話不多說,安裝了這個插件之后(yarn add webpack-dev-server),只要在項目目錄下執行webpack-dev-server命令,訪問本地localhost:8080就可以看到這個頁面了。
但是這個時候當我們修改了一個文件之后還需要重新用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~
