lulusir / my-blog

my-blog
https://github.com/lulusir/my-blog/issues
13 stars 1 forks source link

后端模版的webpack多页配置 #13

Open lulusir opened 6 years ago

lulusir commented 6 years ago

功能:

抽离公共模块optimization

配置

postcss的autoprefixer如何配置

postcss文档
新建一个postcss.config.js

/ postcss.config.js
module.exports = {
  plugins: [
      require('autoprefixer')({
          'browsers': ['ie > 8', 'last 5 versions']
      })
  ]
}

eslint怎么配置

/ .eslintrc.js
module.exports = {
    root: true,
    "env": {
        "browser": true,
        "es6": true
    },
    "extends": "standard",
    "parserOptions": {
        "sourceType": "module"
    },
    'rules': {
        // allow paren-less arrow functions
        'arrow-parens': 0,
        // allow async-await
        'generator-star-spacing': 0,
        // 禁止在非赋值或条件语句中使用 new 操作符
        'no-new': 0,
        'no-useless-escape': 0
      }
};

babel

/ .babelrc

{
  "presets": [
    ["env", { "modules": false }],
    "stage-2"
  ],
  "comments": false,
  "env": {
    "test": {
      "presets": ["env", "stage-2"]
    }
  }
}

weback.config.js

const path = require('path')
const fs = require('fs')
const rm = require('rimraf')
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const InjectPlugin = require('./webpack_plugin/InjectPlugin.js')
// const HtmlWebpackPlugin = require('html-webpack-plugin')
const entry = getEntry(resolve('./src/entry'))
// 删除dist
rm(resolve('dist'), err => {
  if (err) throw err
})

module.exports = {
  entry: entry,
  output: {
    path: resolve('dist'),
    filename: '[name].[hash].js',
  },

  module: {
    rules: [
      {
        enforce: "pre",
        test: /\.js/,
        exclude: /node_modules/,
        use: 'eslint-loader'
      },
      {
        test: /\.jsx?/,
        include: [
          path.resolve(__dirname, 'src')
        ],
        use: ['babel-loader'],
      },
      {
        test: /\.css$/,
        // 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
        use: ExtractTextPlugin.extract({ 
          fallback: 'style-loader',
          use: [
            {
              loader: 'css-loader',
              options: {
                minimize: true
              }
            },
            'postcss-loader'
          ],
        }), 
      },
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {},
          },
        ],
      },
      {
        test: /\.jsx?/, // 支持 js 和 jsx
        include: [
          path.resolve(__dirname, 'src'), // src 目录下的才需要经过 babel-loader 处理
        ],
        loader: 'babel-loader',
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000
        }
      },
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000
        }
      }
    ],
  },

  // 代码模块路径解析的配置
  resolve: {
    modules: [
      "node_modules",
      path.resolve(__dirname, 'js')
    ],
    alias: {
      src: path.resolve(__dirname, 'src')
    },
    extensions: [".js"],
  },

  plugins: [
    new InjectPlugin({
      key: 'index', // 这是对应js的chuangname
      output: resolve('../index/index.html'),
      template: resolve('htmlTemplate/index/index.html')
    }),
    new InjectPlugin({
      key: 'about',
      output: resolve('../index/about.html'),
      template: resolve('htmlTemplate/index/about.html')
    }),
    new InjectPlugin({
      key: 'conference',
      output: resolve('../index/conference.html'),
      template: resolve('htmlTemplate/index/conference.html')
    }),
    new InjectPlugin({
      key: 'league',
      output: resolve('../index/league.html'),
      template: resolve('htmlTemplate/index/league.html')
    }),
    new InjectPlugin({
      key: 'review',
      output: resolve('../index/review.html'),
      template: resolve('htmlTemplate/index/review.html')
    }),
    new ExtractTextPlugin('[name].[hash].css'),
  ],
  optimization: {
    splitChunks: {
      chunks: "all", // 所有的 chunks 代码公共的部分分离出来成为一个单独的文件
      name: 'vendor'
    }
  },
}

function resolve (dir) {
  return path.resolve(__dirname, '.', dir)
}
function getEntry (dir, entryFile) {
  const files = fs.readdirSync(dir)
  return files.reduce((res, k) => {
    const page = path.resolve(dir, k)
    if (fs.existsSync(page)) {
      res[k.replace('.js', '')] = page
    }
    return res
  }, {})
}

现在是使用php的模版,没法动态插入对应的js和css

自己写一个插件,在模版对应的位置注入对应的js和css

/**
 * 
 *   new InjectPlugin({
 *    key: 'index',
 *    output: resolve('../index/index.html'),
 *    template: resolve('htmlTemplate/index/index.html')
 *   }),
 *  @param key 这是对应js的chuckname
 *  @param output html输出的位置
 *  @param template heml 模版的位置
 */
const fs = require('fs')

class InjectPlugin {
  constructor (options) {
    this.options = Object.assign({}, options)
  }

  apply (compiler) {
    compiler.hooks.emit.tap('InjectPlugin', (compilation) => {
      const keys = Object.keys(compilation.assets)
      const injectObj = this.getInjectObj(keys)
      fs.readFile(this.options.template, 'utf8', (err, data) => {
        if (err) throw err

        const writedata = this.replaceSourceInHtml(injectObj, data)

        fs.writeFile(this.options.output, writedata, (err) => {
          if (err) throw err
          console.log('The file has been saved!')
        })
      })
    })
  }

  /**
   * 
   * @param {Array} keys chuckname组成的数组
   */
  getInjectObj (keys) {
    return keys.filter((v) => {
      return v.includes(this.options.key) || v.includes('vendor')
    }).reduce((prev, val) => {
      if (val.includes('js')) {
        if (val.includes('vendor')) {
          prev.vendorJs = val
        } else {
          prev.js = val
        }
      }
      if (val.includes('css')) {
        if (val.includes('vendor')) {
          prev.vendorCss = val
        } else {
          prev.css = val
        }
      }
      return prev
    }, {})
  }

  replaceSourceInHtml (injectObj, htmlData) {
    const replaceCss = `{block name="css"}
    <link rel="stylesheet" href="__STATIC__/dist/${injectObj.vendorCss}">
    <link rel="stylesheet" href="__STATIC__/dist/${injectObj.css}">
    {/block}`
    const replacejs = `{block name="js"}
      <script type=text/javascript src="__STATIC__/dist/${injectObj.vendorJs}"></script>
      <script type=text/javascript src="__STATIC__/dist/${injectObj.js}"></script>
      {/block}`
    let writedata = htmlData.replace('{block name="css"}{/block}', replaceCss)
    writedata = writedata.replace('{block name="js"}{/block}', replacejs)
    return writedata
  }
}
module.exports = InjectPlugin

TODO:

  1. lessloder