使用 webpack3 配置多页应用(二)

在本系列文章的基础上,我对脚手架配置进行了一些优化整理,基于 Webpack4 和 Vue,下面是文章链接:
基于 Webpack4 + Vue 的多页应用解决方案(一)
基于 Webpack4 + Vue 的多页应用解决方案(二)


上篇文章,主要谈到了使用 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

如果将全部文件都列出来的话,太长了,不忍直视,因此我把文件的内容精简了一些:)
其中 .babrlrc 是 babel 的相关配置文件,.eslintrc.js 是 ESLint 相关的配置文件,.gitignore 是 git 仓库上传时的忽略项目,postcss.config.js 是 postcss 相关的配置。

package.json

所有的功能都是从 package.json 的 scripts 入口开始执行的,我想要脚手架有以下功能:

  • 开发环境构建
  • 生产环境构建
  • ESLint 代码检查环境
  • 生产环境构建后的服务器预览环境

在开发或代码检查环境,需要启用 webpack-dev-server 命令,生产环境构建需要启用 webpack 命令,预览环境需要启用 http-server 环境。
上文介绍时把 http-server 给落下了,您现在可以进行如下安装:

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 命令:

  • npm run dev:进入开发环境
  • npm run build:进入生产环境
  • npm run lint:执行代码检查
  • npm run serve:服务器环境下预览(打开浏览器)
  • npm run serve2:服务器环境下预览(不打开浏览器)

默认情况下,使用这些命令都会先引入和 package.js 同目录下的 webpack.config.js 文件。由于我们不会将所有的配置都放在 webpack.config.js 中,而是过环境变量进行区分,在 webpack.config.js 中引用其他的配置文件。
设置环境变量采用的语法:

set NODE_ENV=xxx

这里我们为开发、生产、代码检查和预览这几个环境设置了环境变量。

webpack.config.js

webpack.config.js 文件比较简单,只有两行代码,其作用就是用来引用其他的配置文件:

// 获取环境命令,并去除首尾空格
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 是最基础的配置文件,包含了这些环境都可能使用到的配置。
1)相关插件引入

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`);
})

3)主配置文件一览

module.exports = {
    // 入口文件
    entry:Entries,
    // 启用 sourceMap
    devtool:"cheap-module-source-map",
    // 输出文件
    output:{},
    // 加载器
    module:{
        rules:[
        ],
    },
    // 插件
    plugins:[],
}

4)配置 css 加载器

{
    // 对 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
    }  
  }  
}  

5)配置 js 加载器
js 加载器的配置如下:

{
    test: /\.js$/,
    exclude: /node_modules/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: ['env']
        }
    }
},

6)配置图片加载器
图片加载器的配置如下:

{
    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 文件夹中。
7)配置自定义字体加载器
自定义字体加载器的配置如下:

{
    test: /\.(woff|woff2|eot|ttf|otf)$/,
    use:["file-loader"]
}

8)插件配置
插件配置如下:

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.config.js 和 webpack.config.base.js 文件的配置,鉴于篇幅,将剩下的配置文件放在后文进行介绍。

完。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容