webpack4 构建vue多页工程

webpack4 构建vue多页工程

多页应用开发环境配置

构建开发环境的配置,需要使用到webpack-dev-server,以及webpack4中的mode配置和devServer。

而多页应用的开发则需要使用到html-webpack-plugin这个插件,来构建html

项目的目录结构

-- src
  |-- views
    |-- home
      |-- index.js
      |-- index.html
      |-- index.vue

多页面的entry和页面的构建打包

const setMPA = () => {
  const entrys = {};
    const htmlWebpackPlugins = [];
    
    const entryFiles = glob.sync(path.join(__dirname, "src"));
    
    Object.keys(entryFiles)
      .map((index) => {
        const entry = entryFiles[index];
        
          const match = entry.match(/src\/views\/(.*)\/index\.js/);        
          const pageName = match && match[1];
        
          entrys[pageName] = entry;
          htmlWebpackPlugins(
              new HtmlWebpackPlugin({
                  fileName: `${pageName}.html`,
                    template: path.join(__dirname, `src/views/${pageName}/index.html`),
                    title: `${pageName} title`
                })
            )
      })
    
    return {
      entrys,
        htmlWebpackPlugins
    }
}

webpack.dev.js 开发环境的配置

// webpack.dev.js
const path = require('path');
const glob = require('glob');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const webpack = require('webpack');

const setMPA = () => {
    const entrys = {};
    const htmlWebpackPlugins = [];
    
    const entryFiles = glob.sync(path.join(__dirname, "src"));
    
    Object.keys(entryFiles)
        .map((index) => {
            const entry = entryFiles[index];
        
            const match = entry.match(/src\/views\/(.*)\/index\.js/);        
            const pageName = match && match[1];
        
            entrys[pageName] = entry;
            htmlWebpackPlugins(
                new HtmlWebpackPlugin({
                    fileName: `${pageName}.html`,
                    template: path.join(__dirname, `src/views/${pageName}/index.html`),
                    title: `${pageName} title`
                })
            )
        })
    
    return {
        entrys,
        htmlWebpackPlugins
    }
}

const { entrys, htmlWebpackPlugins } = setMPA();

module.exports = {
    mode: 'development',
    entry: entrys,
    output: {
        filename: 'static/js/[name].js',
        path: path.posix.join(__dirname, 'dist')
    },
    resolve: {
        alias: {
            '@': path.join(__dirname, 'src')
        }
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.(png|jpe?g|gif|svg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            name: 'images/[name].[ext]',
                            limit: 10240
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'fonts/[name].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    'vue-style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.styl(us)?$/,
                use: [
                    'vue-style-loader',
                    'css-loader',
                    'stylue-loader'
                ]
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(),
        // 热加载
        new webpack.HotModuleReplacementPlugin()
    ].concat(htmlWebpackPlugins),
    devServer: {
        contentBase: path.join(__dirname, 'dist'),
        hot: true
    }
}

babelrc的配置,应用与编译ES的语法

/* .babelrc  */
{
  "presets": [
    "@babel/perset-env"
  ]
}

浏览器的兼容版本,>1%==市场的使用份额大于1%

/* .browserslistrc  */
last 2 version
>1%
IOS 7

正式环境配置

vue的正式环境需要配置mode: production,默认开启UglifyJsPlugin(js代码压缩)。

正式环境的资源hash迭代(hash、chunkhash、contenthash)

使用loader配置资源的提取,针对样式的提取使用mini-css-extract-plugin插件去提取,配合html-webpack-plguin把提取出来的css[chunk]配置进去html中

告警信息人性化,使用插件@soda/friendly-errors-webpack-plugin,

/**
 * font and image 资源  --> hash
 * 从js提取出font和image资源
 */
module.exports = {
  module: {
    rules: [
      {
        test: /\.(png|jpe?g|gif|svg)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              name: '[name]_[hash:8].[ext]',
              limit: 10240 // 10k https://www.npmjs.com/package/url-loader#limit
            }
          }
        ]
      },
      {
        test: /\.(woff|woff2|eof|ttf|tof)$/,
        use: [
          {
            loader: 'file-loader', // https://www.npmjs.com/package/file-loader#name
            options: {
              name: '[name]_[hash:8].[ext]' // https://www.npmjs.com/package/file-loader#placeholders
            }
          }
        ]
      }
    ]
  }
}

sass 预处理器,配置时需要注意, css 样式处理,使用到contenthash

 /**
 * css --> contenthash 当css的内容没有任何改变,不会随着js[chunkhash]的改变而改变
 * 遵从js的chunkhash
 * 从js中提取出css到文件中
 */
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      },
      {
        test: /\.(scss|sass)$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          {
            loader: 'sass-loader',
            options: {
              fiber: require('fibers'),
              implemation: require('sass'),
              // indentedSyntax: true
            }
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      },
      {
        test: /\.styl(us)?$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'stylus-loader'
        ]
      }
    ]
  },
  plugins: [
    // https://www.npmjs.com/package/mini-css-extract-plugin
    // 提取出css
    new MiniCssExtractPlugin({
      filename: '[name]_[contenthash:8].css'
    })
  ]
}
const path = requrie('path');
const HtmlWebpackPlguin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const FriendlyErrorsWebpackPlugin = require('@soda/friendly-errors-webpack-plugin');
const webpack = require('webpack');

const setMPA = () => {
  const entrys = {};
    const htmlWebpackPlugins = [];
    
    const entryFiles = glob.sync(path.join(__dirname, "src"));
    
    Object.keys(entryFiles)
      .map((index) => {
        const entry = entryFiles[index];
        
          const match = entry.match(/src\/views\/(.*)\/index\.js/);        
          const pageName = match && match[1];
        
          entrys[pageName] = entry;
          htmlWebpackPlugins(
              new HtmlWebpackPlugin({
                  fileName: `${pageName}.html`,
                    template: path.join(__dirname, `src/views/${pageName}/index.html`),
                    title: `${pageName} title`
                })
            )
      })
    
    return {
      entrys,
        htmlWebpackPlugins
    }
}

const { entrys, htmlWebpackPlguins } = setMPA(); 

module.exports = {
  mode: 'production',
    entry: entrys,
    output: {
      filename: '[name]_[chunkhash:8].js',
        path: path.join(__dirname, 'dist')
    },
    resolve: {
        // 配置文件夹的别名
      alias: {
          '@': path.join(__dirname, 'src')
        }
    },
    module: {
      rules: [
            {
              test: /\.js$/,
                use: 'babel-loader'
            },
            {
              test: /\.vue$/,
                use: [
                    'cache-loader',
                    'vue-loader'
                ]
            },
            {
                test: /\.(png|jpe?g|gif|svg)$/,
                use: [
                  {
                    loader: 'url-loader',
                    options: {
                      name: '[name]_[hash:8].[ext]',
                      limit: 10240 // 10k https://www.npmjs.com/package/url-loader#limit
                    }
                  }
                ]
            },
            {
                test: /\.(woff|woff2|eof|ttf|tof)$/,
                use: [
                    {
                        loader: 'file-loader', // https://www.npmjs.com/package/file-loader#name
                        options: {
                            name: '[name]_[hash:8].[ext]' // https://www.npmjs.com/package/file-loader#placeholders
                        }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                  'css-loader'
                ]
            },
            {
                test: /\.(scss|sass)$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    {
                        loader: 'sass-loader',
                        options: {
                            fiber: require('fibers'),
                            implemation: require('sass'),
                            // indentedSyntax: true
                        }
                    }
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.styl(us)?$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'stylus-loader'
                ]
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin(), // vue-loader15版本之后,需要添加添加此插件
        // 重新打包是清除打包的内容
        new CleanWebpackPlugin(),
        // 提取css
        new MiniCssExtractPlugin({
          filename: '[name]_[contenthash:8].css'
        }),
        // https://www.npmjs.com/package/@soda/friendly-errors-webpack-plugin
        new FriendlyErrorsWebpackPlugin()
    ].concat(htmlWebpackPlugins)
}

你可能感兴趣的:(webpack4 构建vue多页工程)