简体   繁体   English

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

[英]How can I split the JS and CSS into separate HTML files?

I have a very specific requirement where I need to split the JS script tag into one file and the CSS link tag into another file using HtmlWebpackPlugin . 我有一个非常具体的要求,我需要使用HtmlWebpackPlugin将JS脚本标记拆分为一个文件,将CSS链接标记拆分为另一个文件。

At the moment, both script and link tags are going into both files. 目前, 无论是剧本和链接标签进入这两个文件。 Is there a way to do them separately? 有没有办法单独进行?

Here is my current Webpack file: 这是我当前的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

Each .ejs file is empty and generates the following inside the .php files: 每个.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>

Is there a way to separate them? 有没有办法将它们分开?

Also, I noticed it is inserting a head tag for the CSS link; 另外,我注意到它正在为CSS链接插入一个head标签; is there a way to stop this happening? 有没有办法阻止这种情况发生?

With help from @mootrichard I was able to get the answer I needed. 在@mootrichard的帮助下,我得到了我需要的答案。

Steps to take: 采取的步骤:

  1. Separate JS and CSS into their own entry points. 将JS和CSS分成他们自己的入口点。
  2. Set inject: false in HtmlWebpackPlugin configs to stop Webpack doing this. HtmlWebpackPlugin配置中设置inject: false以阻止Webpack执行此操作。
  3. Reference 'common' in the chunks to make the common JS file available for the templates. 在块中引用'common'以使模板可以使用通用JS文件。
  4. Configure the .ejs templates to loop the files array. 配置.ejs模板以循环文件数组。

webpack.config.babel.js 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 js.ejs

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

css.ejs css.ejs

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

Hope this comes to help someone else in future. 希望这能帮助将来的其他人。

Benefit of this approach 这种方法的好处

The reason I needed to separate out JS and CSS into actual separate files was for use in WordPress, where the templates do not have a concept of a 'master' template you inherit from, but instead has basic footer and header includes. 我需要将JS和CSS分离成实际的单独文件的原因是在WordPress中使用,其中模板没有您继承的“主”模板的概念,而是具有基本页脚标题包含。

So if you're using WordPress then this is a pretty good approach to take. 因此,如果你正在使用WordPress,那么这是一个非常好的方法。

Since you're wanting to have separate files with different contents, you probably want to split up your entry points and the filter your chunks. 由于您希望使用具有不同内容的单独文件,因此您可能希望拆分入口点并过滤块。

In both of your instances of HtmlWebpackPlugin , you're setting chunks: ['app'] which includes both your CSS and your JS. 在你的两个HtmlWebpackPlugin实例中,你正在设置chunks: ['app']包括你的CSS和你的JS。

You could have something like: 你可以有类似的东西:

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

Then you could have: 然后你可以:

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'
})

As for the CSS being included in the <head> , you'll want to set inject: false because you're utilizing your own custom templates for creating your HTML files. 至于包含在<head>的CSS,您需要设置inject: false因为您正在使用自己的自定义模板来创建HTML文件。 https://github.com/jantimon/html-webpack-plugin#configuration https://github.com/jantimon/html-webpack-plugin#configuration

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何将此Coffeescript拆分为单独的文件? - How can I split this Coffeescript into separate files? 单独的文件(HTML5,CSS和JS) - separate files (HTML5,CSS & JS) 如何将我的javascript代码拆分成单独的文件? - How can I split my javascript code into separate files? 为什么我不能在单独的html和js文件中使用全局变量? - Why can't I use globals in separate html and js files? 我们可以像在 Angular 中一样创建 Vue.js 组件时将 HTML、JS 和 CSS 文件分开吗? - Can we keep HTML, JS and CSS files separate while creating Vue.js components like in Angular? 如何将外部CSS / JS文件提供给NodeJS应用显示的html文件? - How can I serve external css/js files to html files displayed by a NodeJS app? 如何分隔HTML元素和CSS元素并返回它们? - How can I separate the HTML Elements and the CSS elements and return them? 当我将 css 和 js 分成文件并将它们链接回主 html 时,任务列表的工作方式不同 - Task list doesnt work the same when i separate the css and js into files and link them back to the main html 如何在保持可维护性的同时分离关注点(JS,HTML)? - How can I separate concerns (JS, HTML) while keeping maintainability? 如何从 HTML、CSS、Js 和 Python 文件创建 APK 文件? - How can I Create APK file from HTML, CSS, Js and Python files?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM