/*
* 請使用最新版本nodejs
* 默認配置,是按生產環境的要求設置,也就是使用 webpack -p 命令就可以生成正式上線版本。
* 也可以使用 webpack -d -w 命令,生成用於開發調試的代碼。
* 通常開發使用 node server.dev.js 命令 , server.dev.js基於此配置做了特殊處理, 主要是為了自動刷新和熱更新, 這個服務只是在內存中生成緩存文件,不會在硬盤中生成文件。
* webpack配置,如果出現問題,通常都是路徑問題造成的
*
* 常用命令看package.json中配置的scripts,比如
* "scripts": {
* "d": "node server.dev.js",
* "reset:dist": "rm -fr dist && mkdir -p dist/build && cp -r src/lib dist",
* "p": "npm run reset:dist && ./node_modules/.bin/webpack -p --display-error-details --progress --colors"
* }
*/
//導入Node.js的path模塊,主要用來轉換成絕對路徑,比如path.resolve(__dirname, 'build')
const path = require('path');
//導入webpack整個模塊
//也可以不導入webpack整個模塊,而值導入用到的內置插件模塊
//比如 var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
//這樣后面使用方式為 new CommonsChunkPlugin
//否則為new webpack.optimize.CommonsChunkPlugin
const webpack = require('webpack');
//導入ExtractTextPlugin插件,作用提取代碼中的css生成獨立的CSS文件
const ExtractTextPlugin = require('extract-text-webpack-plugin');
//導入HtmlWebpackPlugin插件,作用按需求生成html頁面,想用好,挺麻煩的,可以不用
const HtmlWebpackPlugin = require('html-webpack-plugin');
//打包配置 webpack配置,多數同時支持String, Array or Object的寫法。單字符串的形式用於簡單情況,key-value對象的形式用於復雜情況。
const config = {
// 入口文件配置,打包輸出的來源
// 多種寫法 entry:'entry.js' or entry:{entry1:'entry1.js'} or entry:{entry1:['entry1a.js', ...]} or etc.
// 通常用path.resolve(__dirname, 'src/entry.js')轉換成絕對路徑,也可以使用相對路徑,比如 './src/entry.js'
entry: {
index: [path.resolve(__dirname, 'src/index.js')],
edit: [path.resolve(__dirname, 'src/edit.js')]
},
//輸出配置
//path 輸出目錄 通常用path.resolve(__dirname, 'build')轉換成絕對路徑,也可以使用相對路徑,比如 './build'
//publicPath 開發代碼中url的轉換拼接處理,通常是代碼中各種資源的地址,比如圖片等, url目錄前綴或完整網址url前綴'http://cdn.com/'
//filename 輸出js文件名,[name]對應entry對象鍵名,也可以指定名字,加上id和hash可以避免緩存問題,webpack會用實際值替換類似[hash]這樣字符串
output: {
path: path.resolve(__dirname, 'dist/build'),
publicPath: './build/',
filename: '[name].[id].[hash].js',
},
//路徑解析配置
resolve: {
//自行補全路徑中文件的后綴, 第一個是空字符串,對應不需要后綴的情況
extensions: ['', '.webpack.js', '.web.js', '.js', '.jsx']
},
//模塊
module: {
//loaders: 加載器
// [
// {
// test:正則表達式,匹配的文件名則使用這個加載器。
// include: 匹配的目錄則進一步處理
// exclude: 匹配的目錄則排除
// loader: `!`用於分隔loader 字符串形式,作用和數組形式一樣
// loaders: ['loader',...] 數組形式,作用和字符串形式一樣
// }
// ]
//
// 如果同一文件需要多個loaders處理,也就是使用loaders: ['loader',...] 數組形式,loader的參數不能使用query:{}寫法了。只能用拼接字符串寫法。
loaders: [
{
//加載css資源,默認寫法loader:'style-loader!css-loader' css為Internal內部形式
//ExtractTextPlugin插件寫法用於生成獨立的css文件,用於external link形式
//生成的獨立CSS文件中的url圖片地址的publicPath,通常JS中的publicPath不一樣,如果一樣可以不設置
test: /\.css$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css-loader',
{
publicPath: "./"
}
)
},
{
//url-loader處理圖片URL,如果圖片小於limit值直接生成`base64` 格式的`dataUrl`,否則輸出圖片,name參數指定輸出目錄和圖片名
//url-loader依賴file-loader
//image-webpack-loader是用來壓縮圖片的,主要是透明PNG
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: [
'url-loader?limit=8192&name=img/[name].[hash].[ext]',
'image-webpack-loader?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}'
]
},
{
//用babel轉碼器加載有es2015和jsx語法的js,輸出為es5語法的js,注意這里只是語法轉碼。
//如果開發代碼中有用到新ES規范中的新對象或屬性方法還需要babel-polyfill才能轉碼成ES5代碼
//class-properties和object-rest-spread,是轉碼類屬性寫法和非數組對象的延展符...,新React常用到的寫法,但還不是ES2015規范
//query對象和.babelrc配置文件內容一致,必須都寫,不然使用webpack的babel-loader會報錯.
test: /\.jsx?$/,
exclude: /(node_modules|lib)/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react'],
plugins: ['transform-class-properties', 'transform-object-rest-spread']
}
}
]
},
//script引入js類庫,通過require或import的方式來使用,卻不希望webpack把它編譯到輸出文件中。
//比如不想這么用 const $ = window.jQuery 而是這么用 const $ = require("jquery") or import $ from "jquery"; 則配置"jquery": "jQuery"
//鍵名是require或from時的字符串,鍵值是js內的全局變量名
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
'baidu-hmt': 'window._hmt',
'lrz': 'lrz',
'iscroll': 'IScroll',
'zepto': 'Zepto',
'fabric': 'fabric',
'react-slick': 'Slider'
},
plugins: [
//輸出獨立的css文件,用於external link形式,如果有多個入口JS共用的CSS,會生成commons.css
new ExtractTextPlugin('[name].[id].[hash].css'),
//把entry中配置的多個js中共用代碼提取生成為單個js, 多參數寫法 new webpack.optimize.CommonsChunkPlugin("commons", "commons.js")
new webpack.optimize.CommonsChunkPlugin({
name: "commons",
filename: "commons.[id].[hash].js"
}),
//按需求生成HTML頁面
//template 模板位置
//inject: 'body' js插入在body元素內部的最后
//chunks 對應入口文件名
//filename 生成的文件名,可以帶上路徑
//options參數對象的值可以自定義,比如這里的libJS
//在模板頁中可以獲得和使用這些數據,可以在模板頁中使用<%= JSON.stringify(htmlWebpackPlugin) %>;輸出查看所有可用的數據
new HtmlWebpackPlugin({
template: 'src/template.html',
inject: 'body',
chunks: ['commons', 'index'],
filename: '../index.html',
title: '最美奧運臉',
libJS: [
//上拉下拉
'./lib/js/iscroll-lite.min.js'
]
}),
new HtmlWebpackPlugin({
template: 'src/template.html',
inject: 'body',
chunks: ['commons', 'edit'],
filename: '../edit.html',
title: '最美奧運臉',
libJS: [
//切換左右拖動
'./lib/js/react-slick.min.js',
//編輯圖片
'./lib/js/fabric.min.js'
]
})
//ProvidePlugin的作用就是在開發代碼內不需要require('react')或import ... from ... 也能使用React
// ,new webpack.ProvidePlugin({
// React: 'react',
// ReactDOM: 'react-dom'
// })
//壓縮代碼,命令行的 webpack -p 會默認使用這個插件壓縮代碼
// ,new webpack.optimize.UglifyJsPlugin({
// compress: {
// warnings: false
// }
// })
]
//webpack-dev-server的配置, 通常弄成獨立的文件,比如server.js,
//或者使用命令行形式,比如npm scripts命令行形式,類似webpack-dev-server -d --inline --hot
//弄webpack-dev-server通常是為了自動刷新和熱更新,配置麻煩
// devServer: {
// contentBase: './',
// host: 'h5.baofeng.com',
// port: 9090, //默認8080
// inline: true //監控文件變化,自動重加載整個頁面
// }
};
// babel-polyfill用來轉換ES2015新的對象和方法,在入口數組中,babel-polyfill必須在入口文件字符串前面,並且必須在入口文件代碼的第一行import或require 'babel-polyfill'
for (let prop in config.entry) {
config.entry[prop].unshift(
'babel-polyfill'
);
}
module.exports = config;