代碼地址:https://github.com/cheer4chai/webpack-learningjavascript
仿照vue-cli開發這個工具的目的是瞭解webpack的基本設置,以及vue-cli的工做原理css
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
若是在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
當使用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,咱們就能夠在本地看到已經打包後的頁面了
由於在平常開發中,咱們每每會須要開發和生產兩種環境,而這兩個環境的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 }) ] })
目錄結構以下圖:
當咱們須要向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~