爲何須要使用 webpack 構建多頁應用呢?由於某些項目使用 SPA 不太合適(大可能是 SEO 的緣由),或者您在作項目時有其餘的需求。
若是你有以下需求:css
有了這些需求,基本上就必須使用 webpack
了。html
首先是項目中須要使用的依賴安裝。node
npm install webpack webpack-dev-server --save-dev
npm install webpack-merge --save-dev
該插件用來對 webpack 配置進行合併操做。jquery
npm install babel-core babel-loader babel-preset-env --save-dev
這系列插件用來對 ES6 語法進行轉換。webpack
npm install css-loader style-loader postcss-loader autoprefixer --save-dev
這系列插件用來處理 CSS 樣式,其中 autoprefixer 是 postcss 的一個插件,用來自動給 CSS 樣式添加前綴。git
該插件將在導入圖片、字體等文件時發揮做用。PS.您也能夠安裝 url-loader 以實現相同的做用:es6
npm install file-loader --save-dev npm install url-loader --save-dev
npm install eslint eslint-loader --save-dev
這些插件用來對 JavaScript 代碼進行檢查。github
npm install html-webpack-plugin --save-dev
該插件用來自動生成 HTML 文件。web
npm install extract-text-webpack-plugin --save-dev
該插件用來將 CSS 抽取到獨立的文件。ajax
npm install clean-webpack-plugin --save-dev
該插件用來對 dist 文件夾進行清理工做,每次打包時先清理以前的 dist 文件夾。
... "devDependencies": { "autoprefixer": "^7.1.3", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-preset-env": "^1.6.0", "clean-webpack-plugin": "^0.1.16", "css-loader": "^0.28.7", "eslint": "^4.6.1", "eslint-loader": "^1.9.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.30.1", "postcss-loader": "^2.0.6", "style-loader": "^0.18.2", "url-loader": "^0.5.9", "webpack": "^3.5.5", "webpack-dev-server": "^2.7.1", "webpack-merge": "^4.1.0" }, ...
使用 webpack 進行項目構建時,咱們有不一樣的目的,所以最好將配置文件進行拆分,以適應不一樣的工做:
├─config │ config.js │ webpack.config.base.js │ webpack.config.dev.js │ webpack.config.lint.js │ webpack.config.prod.js │ webpack.config.js
config.js:一些全局的配置,好比 HTML 文件的路徑、publicPath 等 webpack.config.base.js:最基礎的配置文件 webpack.config.dev.js:開發環境配置文件 webpack.config.lint.js:使用 ESLint 代碼檢查時的配置文件 webpack.config.prod.js:生產環境配置文件 webpack.config.js:主配置文件,根據環境變量引用相應的環境的配置
這些配置文件之間是經過 webpack-merge 這個插件進行合併的。
如何使用 webpack 配置多頁面應用呢?實現多頁面應用的關鍵點在哪裏呢?首先須要簡單看一下多頁應用和單頁應用功能的區別。
只有一個入口頁面(index.html)
這個單頁頁面(index.html)中須要引入打包後的全部 JavaScript 文件
全部的頁面內容徹底由 JavaScript 生成
單頁應用有本身的路由系統,服務器端沒有和路由對應的文件
···
每一個版塊對應一個頁面
每一個頁面須要對公共的 JavaScript 進行引入
每一個頁面還須要引入和其自身對應的 JavaScript 文件
因爲對應了多個頁面,所以不是全部頁面內容都是由 JavaScript 生成的
沒有本身的路由系統,服務器端有對應的靜態文件
···
拋開生成頁面內容和路由系統,咱們能夠看到單頁應用和多頁應用最大的區別就是:
單頁應用須要在入口頁面引入全部的 JavaScript 文件
多頁應用須要在每一個頁面中引入公共的 JavaScript 文件以及其自身的 JavaScript 文件
因爲 CSS 文件是能夠由 extract-text-webpack-plugin 這個插件自動提取並插入到 HTML 頁面的,所以咱們只須要關心如何在 HTML 頁面中引入 JavaScript 文件了。
webpack 在打包時,會將入口文件中的 JavaScript 文件打包到某個目標文件中,在不考慮代碼分割提取的狀況下,一個入口文件會打包爲一個目標文件,多個入口文件會打包爲多個對應的目標文件。
所以,咱們能夠將每一個多頁頁面中的特有的 JavaScript 文件做爲入口文件,在打包時將對應打包成不一樣的 bundle 文件(結果文件),若是你想要的話,還能夠在打包時進行代碼分割處理,將公用代碼抽取成一個文件,而後在 HTML 中引入這些 JavaScript 文件就行了。
總結一下,使用 webpack 配置多頁應用的關鍵點在於:
將每一個頁面中特有的 JavaScript 文件做爲入口文件進行打包
在打包後,每一個頁面中都須要引入這些打包後的文件
您能夠在打包時進行公用代碼提取,而後在 HTML 文件中引入
說了這麼多,其實就是利用了 webpack 多入口文件進行打包。
在使用 webpack 對 JavaScript 文件進行打包時,一般須要在打包的文件名中加一個 hash 字符串用來防止緩存,當咱們修改了 JavaScript 代碼後,打包後的文件名也會發生變化。此時若是手動在 HTML 中引用這些 JavaScript 文件,是很是麻煩的。
所以,咱們指望能自動生成 HTML 文件,並自動引用打包後的 JavaScript 文件。所謂自動生成 HTML 文件,能夠理解爲將源代碼的 HTML 複製到目標文件夾中,同時自動引用打包後的 JavaScript 文件。
要完成這項操做,就須要使用前面安裝的 html-webpack-plugin 這個插件。
首先,在個人項目中,有這麼一些 HTML 頁面,將它們放在 html 文件夾中:
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2017/9/5 18:04 1071 company_intro.html -a---- 2017/9/5 18:04 988 contact_us.html -a---- 2017/9/5 18:04 1131 cooperate.html -a---- 2017/9/5 18:04 1244 enterprise_culture.html -a---- 2017/9/5 18:04 1011 hornors.html -a---- 2017/9/5 18:04 1365 index.html -a---- 2017/9/5 18:04 1769 investment.html -a---- 2017/9/5 18:04 1005 join_us.html -a---- 2017/9/5 18:04 1037 news_center.html -a---- 2017/9/5 18:04 987 news_item.html -a---- 2017/9/5 18:04 1134 operate.html -a---- 2017/9/5 18:04 1255 product.html -a---- 2017/9/5 18:04 1132 schools.html
而後,把這些 HTML 文件名(不要後綴)都寫在 config.js 文件中,以供取用:
module.exports = { HTMLDirs:[ "index", "company_intro", "enterprise_culture", "hornors", "news_center", "news_item", "product", "schools", "operate", "cooperate", "join_us", "contact_us", "investment" ], }
HTMLDirs 是一個數組,其中保存了項目中會用到的全部 HTML 頁面。
接下來,每一個 HTML 頁面都對應一份 JavaScript 代碼,所以在 js 文件夾中創建對應的 JavaScript 文件:
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2017/9/5 18:04 2686 company_intro.js -a---- 2017/9/5 18:04 594 contact_us.js -a---- 2017/9/5 18:04 1725 cooperate.js -a---- 2017/9/8 16:54 3505 enterprise_culture.js -a---- 2017/9/5 18:04 2208 hornors.js -a---- 2017/9/8 16:54 4491 index.js -a---- 2017/9/5 18:04 3180 investment.js -a---- 2017/9/5 18:04 1327 join_us.js -a---- 2017/9/8 16:55 3689 news_center.js -a---- 2017/9/5 18:04 1972 news_item.js -a---- 2017/9/5 18:04 2728 operate.js -a---- 2017/9/5 18:04 2664 product.js -a---- 2017/9/5 18:04 2476 schools.js
這兩項是必須的,只有提供了每一個頁面的 HTML 文件和對應的 JavaScript 文件,才能構建多頁面應用。
同時,可能每一個頁面都有本身的樣式,所以您也能夠在 css 文件夾中創建一些樣式文件:
Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2017/9/5 18:04 419 company_intro.css -a---- 2017/9/5 18:04 167 contact_us.css -a---- 2017/9/5 18:04 214 cooperate.css -a---- 2017/9/5 18:04 926 enterprise_culture.css -a---- 2017/9/5 18:04 255 hornors.css -a---- 2017/9/5 18:04 693 investment.css -a---- 2017/9/5 18:04 136 join_us.css -a---- 2017/9/5 18:04 541 news_center.css -a---- 2017/9/5 18:04 623 news_item.css -a---- 2017/9/5 18:04 342 operate.css -a---- 2017/9/5 18:04 236 product.css -a---- 2017/9/5 18:04 213 schools.css
關於創建樣式這一項,不是必須的。
最後,咱們就可使用 html-webpack-plugin 這個插件來自動生成 HTML 文件了,html-webpack-plugin 插件的用法以下:
// 引入插件 const HTMLWebpackPlugin = require("html-webpack-plugin"); // 引入多頁面文件列表 const { HTMLDirs } = require("./config"); // 經過 html-webpack-plugin 生成的 HTML 集合 let HTMLPlugins = []; // 入口文件集合 let Entries = {} // 生成多頁面的集合 HTMLDirs.forEach((page) => { const htmlPlugin = new HTMLWebpackPlugin({ filename: `${page}.html`, template: path.resolve(__dirname, `../app/html/${page}.html`), chunks: [page, 'commons'], }); HTMLPlugins.push(htmlPlugin); Entries[page] = path.resolve(__dirname, `../app/js/${page}.js`); })
在上面的代碼中,首先引入了所需的插件和變量,而後利用 html-webpack-plugin 循環生成 HTML 頁面。
簡單說下 HTMLWebpackPlugin 構造函數的幾個參數:
filename:生成的 HTML 文件名,我這裏選擇和原始文件名保持一致
template:生成 HTML 文件使用的模板,也就是咱們以前在 html 文件夾中創建的那些文件
chunks:生成 HTML 文件時會自動插入相應的代碼片斷(也就是 JavaScript 文件),我這裏選擇插入每一個頁面對應的 JavaScript 文件,以及最後提取出來的公共文件代碼塊。
關於 chunks 還須要說明一點,chunks 是一個數組,在生成 HTML 文件時會將數組中的對應的 JavaScript 片斷自動插入到 HTML 中,這些片斷也就是 webpack 打包時的 output 選項中的 [name]。這裏只須要寫上 [name] 值就好了,無需使用打包生成的完整名稱,由於這會還沒開始打包呢,打包後生成的名稱咱也不知道。
最後,咱們把這些生成 HTML 文件的配置插入到 HTMLPlugins 這個數組中,同時設置 webpack 的入口文件。
在這個腳手架中,我是這樣劃分項目結構的:
├─app │ ├─css │ ├─html │ ├─img │ ├─js │ └─lib ├─config └─dist ├─css ├─img └─js 其中 app 是項目的源碼,config 是 webpack 相關的一些配置文件,dist 是存放打包後的文件,是由 webpack 自動生成的。 更詳細的文件結構以下: │ .babelrc │ .eslintrc.js │ .gitignore │ package.json │ postcss.config.js │ webpack.config.js │ ├─app │ │ favicon.ico │ │ │ ├─css │ │ main.css │ │ │ ├─html │ │ index.html │ │ │ │ │ ├─img │ │ back.png │ │ │ ├─js │ │ ajax.js │ │ footer.js │ │ index.js │ │ nav.js │ │ public.js │ │ tity_nav.js │ │ │ └─lib │ flexible.js │ normalize.css │ swiper.css │ swiper.js │ └─config config.js webpack.config.base.js webpack.config.dev.js webpack.config.lint.js webpack.config.prod.js
全部的功能都是從 package.json 的 scripts 入口開始執行的,我想要腳手架有如下功能:
npm install http-server --save-dev
scripts 命令行配置以下:
"scripts": { "dev": "set NODE_ENV=dev && webpack-dev-server --open", "build": "set NODE_ENV=prod && webpack -p", "lint": "set NODE_ENV=lint && webpack-dev-server --open", "serve": "http-server ./dist -p 8888 -o", "serve2": "http-server ./dist -p 8888" },
下面是整個 package.json 文件:
{ "name": "xxx", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "set NODE_ENV=dev && webpack-dev-server --open", "build": "set NODE_ENV=prod && webpack -p", "lint": "set NODE_ENV=lint && webpack-dev-server --open", "serve": "http-server ./dist -p 8888 -o", "serve2": "http-server ./dist -p 8888" }, "author": "", "license": "ISC", "devDependencies": { "autoprefixer": "^7.1.3", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-plugin-transform-es2015-spread": "^6.22.0", "babel-preset-env": "^1.6.0", "clean-webpack-plugin": "^0.1.16", "css-loader": "^0.28.7", "eslint": "^4.5.0", "eslint-loader": "^1.9.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.30.1", "http-server": "^0.10.0", "postcss-loader": "^2.0.6", "style-loader": "^0.18.2", "url-loader": "^0.5.9", "webpack": "^3.5.5", "webpack-dev-server": "^2.7.1", "webpack-merge": "^4.1.0" }, "dependencies": {} }
若是您想啓用某個環境,須要使用 npm run xxx 命令:
默認狀況下,使用這些命令都會先引入和 package.js 同目錄下的 webpack.config.js 文件。因爲咱們不會將全部的配置都放在 webpack.config.js 中,而是過環境變量進行區分,在 webpack.config.js 中引用其餘的配置文件。
設置環境變量採用的語法:
set NODE_ENV=xxx
這裏咱們爲開發、生產、代碼檢查和預覽這幾個環境設置了環境變量。
// 獲取環境命令,並去除首尾空格 const env = process.env.NODE_ENV.replace(/(\s*$)|(^\s*)/ig,""); // 根據環境變量引用相關的配置文件 module.exports = require(`./config/webpack.config.${env}.js`) webpack.config.base.js
webpack.config.base.js 是最基礎的配置文件,包含了這些環境均可能使用到的配置。
const path = require("path"); // 引入插件 const HTMLWebpackPlugin = require("html-webpack-plugin"); // 清理 dist 文件夾 const CleanWebpackPlugin = require("clean-webpack-plugin") // 抽取 css const ExtractTextPlugin = require("extract-text-webpack-plugin"); #### 2)自動生成 HTML 的配置 // 引入多頁面文件列表 const config = require("./config"); // 經過 html-webpack-plugin 生成的 HTML 集合 let HTMLPlugins = []; // 入口文件集合 let Entries = {} // 生成多頁面的集合 config.HTMLDirs.forEach((page) => { const htmlPlugin = new HTMLWebpackPlugin({ filename: `${page}.html`, template: path.resolve(__dirname, `../app/html/${page}.html`), chunks: [page, 'commons'], }); HTMLPlugins.push(htmlPlugin); Entries[page] = path.resolve(__dirname, `../app/js/${page}.js`); })
module.exports = { // 入口文件 entry:Entries, // 啓用 sourceMap devtool:"cheap-module-source-map", // 輸出文件 output:{}, // 加載器 module:{ rules:[ ], }, // 插件 plugins:[], }
{ // 對 css 後綴名進行處理 test:/\.css$/, // 不處理 node_modules 文件中的 css 文件 exclude: /node_modules/, // 抽取 css 文件到單獨的文件夾 use: ExtractTextPlugin.extract({ fallback: "style-loader", // 設置 css 的 publicPath publicPath: config.cssPublicPath, use: [{ loader:"css-loader", options:{ // 開啓 css 壓縮 minimize:true, } }, { loader:"postcss-loader", } ] }) },
這裏有兩點須要說明:
A.publicPath:在 css 中設置背景圖像的 url 時,常常會找不到圖片(默認會在 css 文件所在的文件夾中尋找),這裏設置 extract-text-webpack-plugin 插件的 publicPath 爲圖片文件夾所在的目錄,就能夠順利找到圖片了。
在 config.js 中,設置 cssPublicPath 的值:
cssPublicPath:"../"
B.postcss 我主要用來自動添加 css 前綴以及一點美化操做,在使用 postcss 時,須要在 postcss.config.js 中進行配置:
module.exports = { plugins: { 'autoprefixer': { browsers: ['last 5 version','Android >= 4.0'], //是否美化屬性值 默認:true cascade: true, //是否去掉沒必要要的前綴 默認:true remove: true } } }
js 加載器的配置以下:
{ test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['env'] } } },
圖片加載器的配置以下:
{ test: /\.(png|svg|jpg|gif)$/, use:{ loader:"file-loader", options:{ // 打包生成圖片的名字 name:"[name].[ext]", // 圖片的生成路徑 outputPath:config.imgOutputPath } } },
outputPath 規定了輸出圖片的位置,默認狀況下,圖片在打包時會和全部的 HTML/CSS/JS 文件打包到一塊兒,經過設置 outputPath 值能夠將全部的圖片都打包到一個單獨的文件中。
設置 config.js 的 imgOutputPath:
imgOutputPath:"img/",
在打包時,會將全部的圖片打包到 dist 文件夾下的 img 文件夾中。
自定義字體加載器的配置以下:
{ test: /\.(woff|woff2|eot|ttf|otf)$/, use:["file-loader"] }
插件配置以下:
plugins:[ // 自動清理 dist 文件夾 new CleanWebpackPlugin(["dist"]), // 將 css 抽取到某個文件夾 new ExtractTextPlugin(config.cssOutputPath), // 自動生成 HTML 插件 ...HTMLPlugins ],
同打包圖片,在抽取 css 時也能夠指定抽取的目錄,只需將路徑傳入 extract-text-webpack-plugin 插件的構造函數中。
配置 config.js 的 cssOutputPath 選項:
cssOutputPath:"./css/styles.css",
這裏將全部的 css 提取到 dist 文件夾下的 css 文件夾中,並命名爲 style.css。
webpack.config.base.js 詳細配置
下面是 webpack.config.base.js 的詳細配置文件:
const path = require("path"); // 引入插件 const HTMLWebpackPlugin = require("html-webpack-plugin"); // 清理 dist 文件夾 const CleanWebpackPlugin = require("clean-webpack-plugin") // 抽取 css const ExtractTextPlugin = require("extract-text-webpack-plugin"); // 引入多頁面文件列表 const config = require("./config"); // 經過 html-webpack-plugin 生成的 HTML 集合 let HTMLPlugins = []; // 入口文件集合 let Entries = {} // 生成多頁面的集合 config.HTMLDirs.forEach((page) => { const htmlPlugin = new HTMLWebpackPlugin({ filename: `${page}.html`, template: path.resolve(__dirname, `../app/html/${page}.html`), chunks: [page, 'commons'], }); HTMLPlugins.push(htmlPlugin); Entries[page] = path.resolve(__dirname, `../app/js/${page}.js`); }) module.exports = { entry:Entries, devtool:"cheap-module-source-map", output:{ filename:"js/[name].bundle.[hash].js", path:path.resolve(__dirname,"../dist") }, // 加載器 module:{ rules:[ { // 對 css 後綴名進行處理 test:/\.css$/, // 不處理 node_modules 文件中的 css 文件 exclude: /node_modules/, // 抽取 css 文件到單獨的文件夾 use: ExtractTextPlugin.extract({ fallback: "style-loader", // 設置 css 的 publicPath publicPath: config.cssPublicPath, use: [{ loader:"css-loader", options:{ // 開啓 css 壓縮 minimize:true, } }, { loader:"postcss-loader", } ] }) }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['env'] } } }, { test: /\.(png|svg|jpg|gif)$/, use:{ loader:"file-loader", options:{ // 打包生成圖片的名字 name:"[name].[ext]", // 圖片的生成路徑 outputPath:config.imgOutputPath } } }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use:["file-loader"] } ], }, plugins:[ // 自動清理 dist 文件夾 new CleanWebpackPlugin(["dist"]), // 將 css 抽取到某個文件夾 new ExtractTextPlugin(config.cssOutputPath), // 自動生成 HTML 插件 ...HTMLPlugins ], }
這個配置文件主要用來在開發環境使用,須要 webpack-dev-server 這個插件提供支持。該文件的配置以下:
// 引入基礎配置文件 const webpackBase = require("./webpack.config.base"); // 引入 webpack-merge 插件 const webpackMerge = require("webpack-merge"); // 引入配置文件 const config = require("./config"); // 合併配置文件 module.exports = webpackMerge(webpackBase,{ // 配置 webpack-dev-server devServer:{ // 項目根目錄 contentBase:config.devServerOutputPath, // 錯誤、警告展現設置 overlay:{ errors:true, warnings:true } } });
其中,webpack-merge 這個插件用來對配置文件進行合併,在 webpack.config.base.js 的基礎上合併新的配置。
devServer 配置項的 contentBase 項是項目的根目錄,也就是咱們的 dist 目錄,區別在於這個 dist 目錄不是硬盤上的 dist 目錄,而是存在於內存中的 dist 目錄。在使用 webpack-dev-server 時,將會以這個內存中的 dist 目錄做爲根目錄。
devServer 的 overlay 選項中設置了展現錯誤和警告,這樣當代碼發生錯誤時,會將錯誤信息投射到瀏覽器上,方便咱們開發。
這裏將 contentBase 指向了 config 中的一個配置:
devServerOutputPath:"../dist", webpack.config.prod.js
該配置文件用來在生產環境啓用,主要用來壓縮、合併和抽取 JavaScript 代碼,並將項目文件打包至硬盤上的 dist 文件夾中。
// 引入基礎配置 const webpackBase = require("./webpack.config.base"); // 引入 webpack-merge 插件 const webpackMerge = require("webpack-merge"); // 引入 webpack const webpack = require("webpack"); // 合併配置文件 module.exports = webpackMerge(webpackBase,{ plugins:[ // 代碼壓縮 new webpack.optimize.UglifyJsPlugin({ // 開啓 sourceMap sourceMap: true }), // 提取公共 JavaScript 代碼 new webpack.optimize.CommonsChunkPlugin({ // chunk 名爲 commons name: "commons", filename: "[name].bundle.js", }), ] });
在抽取公共的 JavaScript 代碼時,咱們將公共代碼抽取爲 commons.bundle.js,這個公共代碼的 chunk(name)名就是 commons,在使用 html-webpack-plugin 自動生成 HTML 文件時會引用這個 chunk。
webpack.config.lint.js
這項配置用來進行代碼檢查,配置以下:
const webpackBase = require("./webpack.config.base"); const webpackMerge = require("webpack-merge"); const config = require("./config"); module.exports = webpackMerge(webpackBase,{ module:{ rules:[ { test: /\.js$/, // 強制先進行 ESLint 檢查 enforce: "pre", // 不對 node_modules 和 lib 文件夾中的代碼進行檢查 exclude: /node_modules|lib/, loader: "eslint-loader", options: { // 啓用自動修復 fix:true, // 啓用警告信息 emitWarning:true, } }, ] }, devServer:{ contentBase:config.devServerOutputPath, overlay:{ errors:true, warnings:true } } });
在使用 eslint-loader 時,咱們設置了 enforce:"pre" 選項,這個選項表示在處理 JavaScript 以前先啓用 ESLint 代碼檢查,而後再使用 babel 等 loader 對 JavaScript 進行編譯。
在 eslint-loader 的 options 選項中,設置了自動修復和啓用警告信息,這樣當咱們的代碼出現問題時,ESLint 會首先嚐試自動修復(如將雙引號改成單引號),對於沒法自動修復的問題,將以警告或錯誤的信息進行展現。
要想使用 ESLint 進行代碼檢查,除了使用 eslint-loader 以外,還需針對 ESLint 自己進行配置,這就須要一個 .eslintrc.js 文件。該文件的配置以下:
module.exports = { env: { browser: true, commonjs: true, es6: true, node: true, }, extends: 'eslint:recommended', parserOptions: { sourceType: 'module', }, rules: { 'comma-dangle': ['error', 'always-multiline'], indent: ['error', 2], 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], 'no-unused-vars': ['warn'], 'no-console': 0, }, };
{ "name": "xxx", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "set NODE_ENV=dev && webpack-dev-server --open", "build": "set NODE_ENV=prod && webpack -p", "lint": "set NODE_ENV=lint && webpack-dev-server --open", "serve": "http-server ./dist -p 8888 -o", "serve2": "http-server ./dist -p 8888" }, "author": "", "license": "ISC", "devDependencies": { "autoprefixer": "^7.1.3", "babel-core": "^6.26.0", "babel-loader": "^7.1.2", "babel-plugin-transform-es2015-spread": "^6.22.0", "babel-preset-env": "^1.6.0", "clean-webpack-plugin": "^0.1.16", "css-loader": "^0.28.7", "eslint": "^4.5.0", "eslint-loader": "^1.9.0", "extract-text-webpack-plugin": "^3.0.0", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.30.1", "http-server": "^0.10.0", "postcss-loader": "^2.0.6", "style-loader": "^0.18.2", "url-loader": "^0.5.9", "webpack": "^3.5.5", "webpack-dev-server": "^2.7.1", "webpack-merge": "^4.1.0" }, "dependencies": {} }
node_modules dist npm-debug.log .babelrc { "plugins": ["transform-es2015-spread"] }
module.exports = { env: { browser: true, commonjs: true, es6: true, node: true, }, extends: 'eslint:recommended', parserOptions: { sourceType: 'module', }, rules: { 'comma-dangle': ['error', 'always-multiline'], indent: ['error', 2], 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], 'no-unused-vars': ['warn'], 'no-console': 0, }, };
module.exports = { plugins: { 'autoprefixer': { browsers: ['last 5 version','Android >= 4.0'], //是否美化屬性值 默認:true cascade: true, //是否去掉沒必要要的前綴 默認:true remove: true } } }
module.exports = { HTMLDirs:[ "index", "company_intro", "enterprise_culture", "hornors", "news_center", "news_item", "product", "schools", "operate", "cooperate", "join_us", "contact_us", "investment" ], cssPublicPath:"../", imgOutputPath:"img/", cssOutputPath:"./css/styles.css", devServerOutputPath:"../dist", }
// 獲取環境命令,並去除首尾空格 const env = process.env.NODE_ENV.replace(/(\s*$)|(^\s*)/ig,""); // 根據環境變量引用相關的配置文件 module.exports = require(`./config/webpack.config.${env}.js`) webpack.config.base.js const path = require("path"); // 引入插件 const HTMLWebpackPlugin = require("html-webpack-plugin"); // 清理 dist 文件夾 const CleanWebpackPlugin = require("clean-webpack-plugin") // 抽取 css const ExtractTextPlugin = require("extract-text-webpack-plugin"); // 引入多頁面文件列表 const config = require("./config"); // 經過 html-webpack-plugin 生成的 HTML 集合 let HTMLPlugins = []; // 入口文件集合 let Entries = {} // 生成多頁面的集合 config.HTMLDirs.forEach((page) => { const htmlPlugin = new HTMLWebpackPlugin({ filename: `${page}.html`, template: path.resolve(__dirname, `../app/html/${page}.html`), chunks: [page, 'commons'], }); HTMLPlugins.push(htmlPlugin); Entries[page] = path.resolve(__dirname, `../app/js/${page}.js`); }) module.exports = { entry:Entries, devtool:"cheap-module-source-map", output:{ filename:"js/[name].bundle.[hash].js", path:path.resolve(__dirname,"../dist") }, // 加載器 module:{ rules:[ { // 對 css 後綴名進行處理 test:/\.css$/, // 不處理 node_modules 文件中的 css 文件 exclude: /node_modules/, // 抽取 css 文件到單獨的文件夾 use: ExtractTextPlugin.extract({ fallback: "style-loader", // 設置 css 的 publicPath publicPath: config.cssPublicPath, use: [{ loader:"css-loader", options:{ // 開啓 css 壓縮 minimize:true, } }, { loader:"postcss-loader", } ] }) }, { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['env'] } } }, { test: /\.(png|svg|jpg|gif)$/, use:{ loader:"file-loader", options:{ // 打包生成圖片的名字 name:"[name].[ext]", // 圖片的生成路徑 outputPath:config.imgOutputPath } } }, { test: /\.(woff|woff2|eot|ttf|otf)$/, use:["file-loader"] } ], }, plugins:[ // 自動清理 dist 文件夾 new CleanWebpackPlugin(["dist"]), // 將 css 抽取到某個文件夾 new ExtractTextPlugin(config.cssOutputPath), // 自動生成 HTML 插件 ...HTMLPlugins ], }
// 引入基礎配置文件 const webpackBase = require("./webpack.config.base"); // 引入 webpack-merge 插件 const webpackMerge = require("webpack-merge"); // 引入配置文件 const config = require("./config"); // 合併配置文件 module.exports = webpackMerge(webpackBase,{ // 配置 webpack-dev-server devServer:{ // 項目根目錄 contentBase:config.devServerOutputPath, // 錯誤、警告展現設置 overlay:{ errors:true, warnings:true } } });
// 引入基礎配置 const webpackBase = require("./webpack.config.base"); // 引入 webpack-merge 插件 const webpackMerge = require("webpack-merge"); // 引入 webpack const webpack = require("webpack"); // 合併配置文件 module.exports = webpackMerge(webpackBase,{ plugins:[ // 代碼壓縮 new webpack.optimize.UglifyJsPlugin({ // 開啓 sourceMap sourceMap: true }), // 提取公共 JavaScript 代碼 new webpack.optimize.CommonsChunkPlugin({ // chunk 名爲 commons name: "commons", filename: "[name].bundle.js", }), ] });
const webpackBase = require("./webpack.config.base"); const webpackMerge = require("webpack-merge"); const config = require("./config"); module.exports = webpackMerge(webpackBase,{ module:{ rules:[ { test: /\.js$/, // 強制先進行 ESLint 檢查 enforce: "pre", // 不對 node_modules 和 lib 文件夾中的代碼進行檢查 exclude: /node_modules|lib/, loader: "eslint-loader", options: { // 啓用自動修復 fix:true, // 啓用警告信息 emitWarning:true, } }, ] }, devServer:{ contentBase:config.devServerOutputPath, overlay:{ errors:true, warnings:true } } });
│ .babelrc │ .eslintrc.js │ .gitignore │ package.json │ postcss.config.js │ webpack.config.js │ ├─app │ │ favicon.ico │ │ │ ├─css │ │ main.css │ │ │ ├─html │ │ index.html │ │ │ │ │ ├─img │ │ back.png │ │ │ ├─js │ │ ajax.js │ │ footer.js │ │ index.js │ │ nav.js │ │ public.js │ │ tity_nav.js │ │ │ └─lib │ flexible.js │ normalize.css │ swiper.css │ swiper.js │ └─config config.js webpack.config.base.js webpack.config.dev.js webpack.config.lint.js webpack.config.prod.js
cnpm i jquery --save const ProvidePlugin = new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', });
{ // s?css => scss或者css test:/\.s?css$/, // 不處理 node_modules 文件中的 css 文件 exclude: /node_modules/, // 抽取 css 文件到單獨的文件夾 use: ExtractTextPlugin.extract({ fallback: "style-loader", // 設置 css 的 publicPath publicPath: config.cssPublicPath,//在 css 中設置背景圖像的 url 時,常常會找不到圖片(默認會在 css 文件所在的文件夾中尋找),這裏設置 extract-text-webpack-plugin 插件的 publicPath 爲圖片文件夾所在的目錄,就能夠順利找到圖片了 use: [{ loader:"css-loader", options:{ // 開啓 css 壓縮 minimize:true, } }, { loader:"postcss-loader", }, { loader:"sass-loader", //啓用sass 雖然在這隻寫了sass-loader 但還要下載node-sass } ] }) },
{ test: /\.js$/, exclude: /^node_modules*swiper$/, use: { loader: 'babel-loader', options: { presets: ['env'] } } },