为何须要使用 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'] } } },