将webpack与现有的PHP和JS项目一起使用

时间:2017-04-16 11:30:08

标签: php jquery css node.js webpack

我有一个带有jquery和bootstrap的现有PHP项目,没有使用任何前端框架。

我正在尝试使用webpack模块bundler为我的项目资源创建一个入口点,使用node js package manager管理js依赖项,运行minify js css,image re-size等等任务。并改善加载单个页面所需的浏览器加载时间。

我遇到了webpack教程,并安装了它并安装了它的开发服务器,但问题是我无法理解如何在项目中转换所有当前的js脚本和css链接(我在哪里)有很多jquery和CSS库用于在项目中提供多个功能)来使用webpack。

我是否必须以适合webpack的方式重写所有JS和CSS文件?如何成功迁移?

此外,我无法在webpack dev-server上运行我当前的php应用程序,它是否意味着首先在那里运行?它只列出了项目目录。

我创建了一个测试index.js文件并使用了以下webpack配置:

var path = require('path');
var webpack = require('webpack');

module.exports =
{
    entry: [
        './public/js/index.js',
        'webpack/hot/dev-server',
        'webpack-dev-server/client?http://localhost:8080'
    ],
    plugins: [
      new webpack.HotModuleReplacementPlugin()
    ],
    output: {
        path: path.join(__dirname, "public/dist/js"),
        publicPath : "http://localhost:8080/my_proj/public/dist/js",
        filename: "bundle.js"
    }

};

我将bundle.js添加到我的脚本加载中仅用于测试,如下所示,希望应用程序将在webpack dev-server上运行:

<script type="text/javascript" src="public/dist/js/bundle.js"></script>
<script type="text/javascript" src="public/js/jquery.min.js"></script>
<script type="text/javascript" src="public/js/jquery.migrate.js"></script>
<script type="text/javascript" src="public/js/jquery.bxslider.min.js"></script>
<script type="text/javascript" src="public/js/jquery.appear.js"></script>
<script type="text/javascript" src="public/js/jquery.countTo.js"></script>
<script type="text/javascript" src="public/js/bootstrap.js"></script>

请帮助我理解此处的概念以及如何成功完成此迁移?

2 个答案:

答案 0 :(得分:121)

首先,回答你的小问题:

  • 不,你不应该通过webpack dev服务器运行你的PHP应用程序。在下面的实时重新载入部分进行了解释。
  • 不,您不必重写资产。大概。请参阅下面的 CSS Edge Cases 部分。

免责声明:我只会提出您问题的一小部分内容。它的范围太宽泛,无法包含在一个StackOverflow答案中。

我只会与

取得联系
  • 为webpack设置开发和生产环境
  • 捆绑您的第一个JavaScript

应该为你奠定基础。

我还会提到一些您可能想要添加的内容,并根据资源进行链接以便阅读。

所以,让我们走吧。

要求

我假设你的机器上安装了Node.js和npm,并且大致知道如何使用它们。

我还假设您已将webpackwebpack-cli安装为项目的(dev)依赖项(不仅仅是全局):

npm install --save-dev webpack webpack-cli
  

更新:此答案的早期版本不需要安装webpack-cli。从版本4(2018年2月)开始,webpack的CLI位于自己的包中,因此需要额外的包。

设置开发和生产工作流程

您通常希望在开发中使用与生产中不同的东西(在生产中缩小,在开发中实时重新加载......)

为实现这一目标,我们希望拆分配置文件。

准备目录结构

我们同意忽略您问题中的webpack配置。我们将从头开始,无论如何我们都必须改变一切。

首先,在项目根目录中创建一个build文件夹。与构建相关的东西会去那里,因为我们不想用配置文件污染项目的根文件夹。 (您可以自由地以不同的方式命名此文件夹,但在本教程中会对此进行跟踪。)

在该文件夹中创建config.base.jsconfig.production.jsconfig.development.js文件。

很好,我们现在有两个构建链的配置文件。虽然配置仍然是空的,所以现在让我们用一些基本逻辑填充它们。

安装webpack-merge

但首先,我们需要安装webpack-merge

npm install --save-dev webpack-merge

这个包允许我们深度合并多个webpack配置。我们希望根据当前环境使用它来创建webpack配置。

调整配置

现在调整build/config.base.js

module.exports = {
  // We'll place webpack configuration for all environments here
}

该文件显然现在只是导出一个空对象,但我们需要执行以下步骤。

将此代码放入build/config.production.js

const merge = require('webpack-merge')

module.exports = merge(require('./config.base.js'), {
  mode: 'production'

  // We'll place webpack configuration for production environment here
})

几乎相同的代码会进入您的build/config.development.js

const merge = require('webpack-merge')

module.exports = merge(require('./config.base.js'), {
  mode: 'development',
  watch: true

  // All webpack configuration for development environment will go here
})

我认为这非常直观:

使用带有config.development.js配置的webpack将获取通用配置并合并其自己的配置声明。

  

更新:上述配置文件中的mode选项已添加到webpack 4(2018年2月发布)中。它为开发和生产包设置了a bunch of sensible defaults

现在,从命令行运行该过程将如下所示:

npx webpack --config build/config.development.js

# If the above doesn't work, you probably have an older version of npm (< 5.1) installed
# While npx is a really great tool, you can of course still call the path of the webpack executable manually:

node_modules/.bin/webpack --config build/config.development.js

...反之亦然production环境。

这个命令使用起来相当笨拙,但不用担心,我们稍后会解决这个问题。

制作一些帮助文件

我们希望集中信息以使其易于交换。文件路径就是这样的东西。所以让我们提取它们。

paths.js文件夹中创建build并让它导出我们稍后想要使用的路径:

const path = require('path')

// I'm really just guessing your project's folder structure from reading your question,
// you might want to adjust this whole section
module.exports = {
  // The base path of your source files, especially of your index.js
  SRC: path.resolve(__dirname, '..', 'public'),

  // The path to put the generated bundle(s)
  DIST: path.resolve(__dirname, '..', 'public', 'dist'),

  /*
  This is your public path.
  If you're running your app at http://example.com and I got your DIST folder right,
  it'll simply be "/dist".
  But if you're running it locally at http://localhost/my/app, it will be "/my/app/dist".

  That means you should probably *not* hardcode that path here but write it to a
  machine-related config file. (If you don't already have something like that,
  google for "dotenv" or something similar.)
  */
  ASSETS: '/dist'
}

创建别名

如上所述,我们可以在技术上以development模式运行我们的构建链,如下所示:

npx webpack --config build/config.development.js

虽然这是一个令人不安的冗长命令,所以让我们改变它。

通过npm脚本运行构建过程更方便。每个环境为您的package.json添加一个脚本,如下所示:

{
  "scripts": {
    "dev": "webpack --config build/config.development.js",
    "prod": "webpack --config build/config.production.js"
  }
}

现在,您可以使用npm run dev resp运行构建链。 npm run prod - 更容易记忆,输入速度更快。

......当然,只要有什么东西可以建立。

捆绑JavaScript

好的,到目前为止,这实际上是相当多的工作而没有达到太多。

让我们从更令人兴奋的事情开始:我们将定义一个JavaScript入口点。

定义入口点

将以下代码放入build/config.base.js(完全替换现有代码):

const path = require('path')
const { SRC, DIST, ASSETS } = require('./paths')

module.exports = {
  entry: {
    scripts: path.resolve(SRC, 'js', 'index.js')
  },
  output: {
    // Put all the bundled stuff in your dist folder
    path: DIST,

    // Our single entry point from above will be named "scripts.js"
    filename: '[name].js',

    // The output path as seen from the domain we're visiting in the browser
    publicPath: ASSETS
  }
}

创建JavaScript文件

上述配置要求index.js生成SRC/js文件夹(如build/paths.js中所定义)。

让我们使用以下内容创建该文件:

import './jquery.min.js'
import './jquery.migrate.js'
import './jquery.bxslider.min.js'
import './jquery.appear.js'
import './jquery.countTo.js'
import './bootstrap.js'

如您所见,index.js只会导入您要使用的所有文件。

如果你现在运行

npm run prod
从您的终端

,将在scripts.js文件夹中创建DIST文件。你可以用一个简单的ol&#39;将它包含在你的标记中。 <script>代码。

恭喜,您已经开始使用网络包了!

深入潜水

这个迷你教程真的只是简单地说明了你可以用webpack做什么。它为您的配置提供了坚实的基础,您现在可以根据需要填写。这实际上将是很多东西。

我会列出一些您可能想要增强的内容,并提供一些可供阅读的链接。

webpack Concepts

如果您想使用webpack,如果您不了解其基本概念,则可能很难这样做。 Juho Vepsäläinen为webpack入门创建了一个很好的指南,这对我帮助很大。他也是webpack的核心贡献者,所以你可以确定他知道他在说什么。

特别是加载器是您真正需要知道的概念。

此列表中的许多提示也在那里解释。

了解详情:SurviveJS – webpack tutorial

代码拆分

这就是名称所说的:您可能不想将所有JavaScript打包成一个庞大的输出文件。

这是webpack所做的工作,可以拆分您在应用程序的某些页面上只需要的部分内容。

此外,根据您处理项目JavaScript的频率,最好从捆绑包中拆分第三方代码以用于缓存目的。

了解详情:webpack Documentation – Code Splitting

缓存

您可能希望通过向捆绑文件名添加哈希来增强站点的缓存行为,这取决于其内容。这将创建(例如)script.31aa1d3cad014475a618.js而不是scripts.js

然后可以无限期缓存该文件,因为只要其内容发生更改,文件名也会更改。

然后,您的PHP代码可能会使用webpack-manifest-plugin来访问生成的文件名。

了解更多:

Transpiling

如果您想在您网站的JavaScript中使用现代ES2015代码(并且定位非常青网浏览器),您需要将它们转换为常规ES5。 (如果术语&#34; ES2015&#34;对您没有任何意义,您很可能不会使用它并且可以忽略此段。)

了解详情:babel-loader – A loader that runs Babel on your scripts

CSS

有CSS的webpack加载器。和萨斯。和PostCSS。无论你需要什么。

由于您可能不打算通过<script>标记添加CSS,因此请了解 Extract Text Plugin 以生成实际的.css文件。< / p>

  

更新: 提取文字插件已经建立。但是,它实际上是一种黑客攻击:即使webpack只知道JavaScript作为目标语言,它也会生成.css个文件。

     

然而,从webpack 4开始,这已不再适用。现在有一个定义任意模块类型的系统,包括CSS。

     

长话短说:Expect native CSS support in webpack to replace Extract Text Plugin some time soon

提示:路径

我会提到这一点,因为这对我来说是一个真正的痛点,直到我意识到webpack如何在这里工作:

请注意,webpack会识别您的url(...)语句,并尝试相对于您的源文件解析

这意味着,您的源文件public/css/main.css

body {
  background: url('../img/bg.jpg');
}

如果您的输出路径为public/dist/css/bundle.css,则会转换为:

body {
  background: url('../../img/bg.jpg');
}

了解更多:

涅槃

  

更新:由于webpack 4于2018年2月发布,因此该部分已过时。将新mode选项设置为"production"现在会自动应用JavaScript缩小。

有一个Terser插件可供webpack缩小您的JavaScript。缩小CSS是已经内置于上述css-loader插件的功能。

了解详情:Terser webpack Plugin

图像优化

webpack是一个捆绑器,而不是任务运行器。因此,图像优化不是真正的webpack任务。您可能最好使用实际的任务运行器或仅为此定义一些npm脚本。

这并不意味着webpack无法做到这一点。几乎所有东西都有插件。

了解更多:

实时重新加载

实时重新加载的问题有一个非常简单的原因:webpack dev服务器只是一个简单的Node.js服务器,只提供静态文件。

对于你而言,webpack-dev-server可能是错误的工具。请尝试使用webpack-livereload-plugin代替您可以通过<script>代码添加的实时重新加载器。

了解详情:webpack-livereload-plugin

源地图

  

更新:从webpack 4(2018年2月发布)开始,当新的mode选项设置为"development"时,会自动生成源地图。

一定要使用源地图。他们会让您更轻松地使用捆绑包来工作。

了解详情:webpack Documentation – Source Maps

边缘案例

通常,您使用webpack处理的所有现有脚本应该运行得很好。

现在我想到的唯一例外是关于全球实体。

请查看以下代码:

function myFunc () {
  console.log('I exist!')
}

普通JavaScript文件中的此代码将使myFunc在JS代码中随处可用。但是由于webpack包代码被包装在回调函数中(因此离开了全局范围),因此不再能够访问该函数。

第三方库不应该是一个问题,它们通常直接将它们的全局变量分配给window对象,但如果您已经在项目中编写了JS代码,那么您应该知道这一点。

自动化!

您希望自动化尽可能多的工作流程。

在推/拉之前,考虑通过git hook运行npm run prod

希望这有帮助。

答案 1 :(得分:0)

根据现有的vue-templates和@Loilo的回答,我制作了一个vue模板,您可以使用vue-cli进行安装。此模板可以快速启动您可以扩展或集成到现有环境中的vue应用程序。

npm install -g vue-cli
vue init delcon/webpack-simple my-project
cd my-project
npm install

<强> devwatch:

此模板有一个额外的运行devwatch选项,用于监视文件更改而不是使用webpack-dev-server。这使它可用于任何现有的网络服务器环境。

npm run devwatch

<强> dev的:

使用默认的webpack-dev-server运行它,删除<script src="http://localhost:35729/livereload.js"></script>中的index.html

npm run dev

<强>构建

构建生产项目:

npm run build