如何将JS和CSS拆分为单独的HTML文件?

时间:2018-02-20 20:43:00

标签: javascript webpack webpack-2 html-webpack-plugin

我有一个非常具体的要求,我需要使用HtmlWebpackPlugin将JS脚本标记拆分为一个文件,将CSS链接标记拆分为另一个文件。

目前, 脚本和链接标记都会进入两个文件。有没有办法单独进行?

这是我当前的Webpack文件:

import webpack from 'webpack'
import path from 'path'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import autoprefixer from 'autoprefixer'

const extractCSS = new ExtractTextPlugin({
  filename: 'css/app.bundle.css',
  allChunks: true
})

const createCSSfile = new HtmlWebpackPlugin({
  chunks: ['app'],
  minify: {
    collapseWhitespace: true
  },
  hash: true,
  template: 'src/ejs/css.ejs',
  filename: 'templates/css.php'
})

const createJSfile = new HtmlWebpackPlugin({
  chunks: ['app'],
  minify: {
    collapseWhitespace: true
  },
  hash: true,
  template: 'src/ejs/js.ejs',
  filename: 'templates/js.php'
})

const config = {
  entry: {
    'app': [
      path.resolve(__dirname, 'src/js/app.js'),
      path.resolve(__dirname, 'src/scss/app.scss')
    ]
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/dist',
    filename: 'js/app.bundle.js',
    sourceMapFilename: 'js/app.bundle.map'
  },
  devtool: 'source-map',
  watch: true,
  watchOptions: {
    ignored: /node_modules/,
    aggregateTimeout: 300,
    poll: 1000
  },
  module: {
    rules: [
      {
        test: /\.(png|gif|jpg|jpeg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '/images/[name].[ext]'
            }
          }
        ]
      },
      {
        test: /\.(eot|ttf|woff|woff2|otf)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '/fonts/[name].[ext]'
            }
          }
        ]
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
            plugins: [require('@babel/plugin-proposal-object-rest-spread')]
          }
        }
      },
      {
        test: /\.scss$/,
        use: extractCSS.extract([
          {
            loader: 'css-loader'
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins () {
                return [
                  autoprefixer({
                    browsers: [
                      'last 2 versions',
                      'Safari >= 8',
                      'Explorer >= 9',
                      'Android >= 4'
                    ]
                  })
                ]
              }
            }
          },
          {
            loader: 'sass-loader'
          }
        ])
      }
    ]
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': {
        'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
      }
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'js/app.common',
      filename: 'js/app.common.js',
      minChunks: 2
    }),
    createCSSfile,
    createJSfile,
    extractCSS
  ]
}

export default config

每个.ejs文件都为空,并在.php文件中生成以下内容:

<head><link href="/dist/css/app.bundle.css?bdba9ec6846a7d92d61f" rel="stylesheet"></head><script type="text/javascript" src="/dist/js/app.bundle.js?bdba9ec6846a7d92d61f"></script>

有没有办法将它们分开?

另外,我注意到它正在为CSS链接插入head标记;有没有办法阻止这种情况发生?

2 个答案:

答案 0 :(得分:12)

在@mootrichard的帮助下,我得到了我需要的答案。

采取的步骤:

  1. 将JS和CSS分成各自的入口点。
  2. inject: false配置中设置HtmlWebpackPlugin以阻止Webpack执行此操作。
  3. 参考&#39;常见&#39;在块中为模板提供通用的JS文件。
  4. 配置.ejs模板以循环文件阵列。
  5. <强> webpack.config.babel.js

    import webpack from 'webpack'
    import path from 'path'
    import HtmlWebpackPlugin from 'html-webpack-plugin'
    import ExtractTextPlugin from 'extract-text-webpack-plugin'
    import autoprefixer from 'autoprefixer'
    
    const extractCSS = new ExtractTextPlugin({
      filename: 'css/app.bundle.css',
      allChunks: true
    })
    
    const createCSSfile = new HtmlWebpackPlugin({
      chunks: ['css'],
      excludeChunks: ['js', 'common'],
      minify: {
        collapseWhitespace: true,
        preserveLineBreaks: true,
        removeComments: true
      },
      inject: false,
      hash: true,
      template: 'src/ejs/css.ejs',
      filename: 'templates/css.php'
    })
    
    const createJSfile = new HtmlWebpackPlugin({
      chunks: ['js', 'common'],
      excludeChunks: ['css'],
      minify: {
        collapseWhitespace: true,
        preserveLineBreaks: true,
        removeComments: true
      },
      inject: false,
      hash: true,
      template: 'src/ejs/js.ejs',
      filename: 'templates/js.php'
    })
    
    const config = {
      entry: {
        'css': [
          path.resolve(__dirname, 'src/scss/app.scss')
        ],
        'js': [
          path.resolve(__dirname, 'src/js/app.js')
        ]
      },
      output: {
        path: path.resolve(__dirname, 'build'),
        publicPath: '/build',
        filename: 'js/app.bundle.js',
        sourceMapFilename: 'js/app.bundle.map'
      },
      devtool: 'source-map',
      watch: true,
      watchOptions: {
        ignored: /node_modules/,
        aggregateTimeout: 300,
        poll: 1000
      },
      module: {
        rules: [
          {
            test: /\.(png|gif|jpg|jpeg)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  name: '/images/[name].[ext]'
                }
              }
            ]
          },
          {
            test: /\.(eot|ttf|woff|woff2|otf)$/,
            use: [
              {
                loader: 'file-loader',
                options: {
                  name: '/fonts/[name].[ext]'
                }
              }
            ]
          },
          {
            test: /\.js$/,
            exclude: /(node_modules|bower_components)/,
            use: {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-env'],
                plugins: [require('@babel/plugin-proposal-object-rest-spread')]
              }
            }
          },
          {
            test: /\.scss$/,
            use: extractCSS.extract([
              {
                loader: 'css-loader'
              },
              {
                loader: 'postcss-loader',
                options: {
                  plugins () {
                    return [
                      autoprefixer({
                        browsers: [
                          'last 2 versions',
                          'Safari >= 8',
                          'Explorer >= 9',
                          'Android >= 4'
                        ]
                      })
                    ]
                  }
                }
              },
              {
                loader: 'sass-loader'
              }
            ])
          }
        ]
      },
      plugins: [
        new webpack.DefinePlugin({
          'process.env': {
            'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
          }
        }),
        new webpack.optimize.CommonsChunkPlugin({
          name: 'common',
          filename: 'js/app.common.js',
          minChunks: 2
        }),
        createCSSfile,
        createJSfile,
        extractCSS
      ]
    }
    
    export default config
    

    <强> js.ejs

    <% for (let i = 0; i < htmlWebpackPlugin.files.js.length; i++) { %>
      <script src="<%= htmlWebpackPlugin.files.js[i] %>"></script>
    <% } %>
    

    <强> css.ejs

    <% for (let i = 0; i < htmlWebpackPlugin.files.css.length; i++) { %>
      <link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[i] %>">
    <% } %>
    

    希望将来帮助其他人。

    这种方法的好处

    我需要将JS和CSS分成实际的单独文件的原因是在WordPress中使用,其中模板没有“主人”的概念。您继承的模板,但具有基本的页脚标题包含。

    因此,如果您正在使用WordPress,那么这是一个非常好的方法。

答案 1 :(得分:6)

由于您希望使用具有不同内容的单独文件,因此您可能希望拆分入口点并过滤您的块。

HtmlWebpackPlugin的两个实例中,您正在设置包含CSS和JS的chunks: ['app']

你可以拥有类似的东西:

entry: {
  'js': [
     path.resolve(__dirname, 'src/js/app.js')
  ],
  'css': [
     path.resolve(__dirname, 'src/scss/app.scss')
  ]
},

然后你可以:

const createCSSfile = new HtmlWebpackPlugin({
    chunks: ['css'],
    minify: {
        collapseWhitespace: true
    },
    hash: true,
    inject: false,
    template: 'src/ejs/css.ejs',
    filename: 'templates/css.php'
})

const createJSfile = new HtmlWebpackPlugin({
    chunks: ['js'],
    minify: {
        collapseWhitespace: true
    },
    hash: true,
    inject: false,
    template: 'src/ejs/js.ejs',
    filename: 'templates/js.php'
})

至于<head>中包含的CSS,您需要设置inject: false,因为您正在使用自己的自定义模板来创建HTML文件。 https://github.com/jantimon/html-webpack-plugin#configuration